View Javadoc

1   
2   /*
3    * Copyright (C) 2005 by Arno Schumacher
4    *
5    * This file is part of net.sourceforge.servletspy
6    *
7    * net.sourceforge.servletspy is free software; you can redistribute
8    * it and/or modify it under the terms of the GNU General Public 
9    * License as published by the Free Software Foundation; either 
10   * version 2, or (at your option) any later version.
11   *
12   * net.sourceforge.servletspy is distributed in the hope that it will
13   * be useful, but WITHOUT ANY WARRANTY; without even the implied 
14   * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
15   * See the GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with this program; if not, write to the Free Software
19   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA 
20   */
21  
22  package net.sourceforge.servletspy.ctx;
23  
24  import java.io.ByteArrayOutputStream;
25  import java.io.PrintWriter;
26  import java.lang.reflect.InvocationTargetException;
27  import java.util.HashMap;
28  import java.util.Map;
29  
30  import net.sourceforge.servletspy.IContext;
31  import net.sourceforge.servletspy.IContextHandler;
32  import net.sourceforge.servletspy.Node;
33  import net.sourceforge.servletspy.util.ClassUtil;
34  
35  import org.apache.commons.logging.Log;
36  import org.apache.commons.logging.LogFactory;
37  
38  /***
39   * @author arno schumacher
40   */
41  public final class Context implements IContext {
42  
43      /*** The logger. */
44      private static final Log LOGGER = LogFactory.getLog(Context.class);
45  
46      /***
47       * Calculates a default serialization result value.
48       * 
49       * @param subject
50       *            The subject to serialize
51       * @return The default value.
52       */
53      private static String determineDefaultValue(final Object subject) {
54          
55          if (subject == null) {
56              return "";
57          } else {
58              return ClassUtil.getClassName( subject.getClass() );
59          }
60      }
61  
62      /*** Map holding already processed subjects, for cycle detection purpose. */
63      private final Map introspected;
64  
65      /***
66       * The result node, a container holding the serialization result and a set
67       * of child nodes.
68       */
69      private Node node;
70  
71      /*** The object for which a node tree has to be calculated. */
72      private Object subject;
73  
74      /*** The transformers responsible for generating the node tree. */
75      private final IContextHandler[] transformers;
76  
77      /*** The index of the <i>current</i> transformer. */
78      private int transformerIndex = -1;
79  
80      /***
81       * Constructor.
82       * 
83       * @param name
84       *            The name of the context.
85       * @param pSubject
86       *            The object to serialize.
87       * @param parentContext
88       *            The parent context.
89       */
90      private Context(final String name, final Object pSubject,
91              final Context parentContext) {
92          this.subject = pSubject;
93          this.transformers = parentContext.transformers;
94          this.introspected = new HashMap(parentContext.introspected);
95          this.node = new Node(parentContext.node, name,
96                  determineDefaultValue(pSubject));
97      }
98  
99      /***
100      * Constructor.
101      * 
102      * @param name
103      *            The name of the context.
104      * @param pSubject
105      *            The object to serialize
106      * @param pTransformers
107      *            The chain of transformers responsible for the serialization
108      *            task.
109      */
110     public Context(final String name, final Object pSubject,
111             final IContextHandler[] pTransformers) {
112         this.node = new Node(null, name, determineDefaultValue(pSubject));
113         this.subject = pSubject;
114         this.introspected = new HashMap();
115         this.transformers = pTransformers;
116     }
117 
118     /*
119      * (non-Javadoc)
120      * 
121      * @see net.sourceforge.servletspy.IContext#add(java.lang.String,
122      *      java.lang.Object)
123      */
124     public void add(final String name, final Object pSubject) {
125         final Context ctx = new Context(name, pSubject, this);
126         ctx.proceed();
127         if (ctx.getNode() != null) {
128             this.getNode().addChildNode(ctx.getNode());
129         }
130     }
131 
132     /***
133      * Returns the map holding the already serialized subjects.
134      * 
135      * @return The map of the already serialized subjects.
136      */
137     public Map getIntrospectedMap() {
138         return introspected;
139     }
140 
141     /*
142      * (non-Javadoc)
143      * 
144      * @see net.sourceforge.servletspy.IContext#getName()
145      */
146     public String getName() {
147         if (getNode() == null) {
148             throw new IllegalStateException();
149         }
150         return getNode().getName();
151     }
152 
153     /***
154      * Returns the node associated with this context.
155      * 
156      * @return The node.
157      */
158     public Node getNode() {
159         return node;
160     }
161 
162     /*
163      * (non-Javadoc)
164      * 
165      * @see net.sourceforge.servletspy.IContext#getSubject()
166      */
167     public Object getSubject() {
168         return subject;
169     }
170 
171     /*
172      * (non-Javadoc)
173      * 
174      * @see net.sourceforge.servletspy.IContext#getValue()
175      */
176     public String getValue() {
177         return getNode() == null ? null : getNode().getValue();
178     }
179 
180     private void handleException(final Throwable exception) {
181         LOGGER.info("Caught exception:", exception);
182         if (node != null) {
183             ByteArrayOutputStream bytes = new ByteArrayOutputStream();
184             PrintWriter writer = new PrintWriter(bytes, true);
185             exception.printStackTrace(writer);
186             if (node.getValue() == null || node.getValue().length() == 0) {
187                 node.setValue(bytes.toString());
188             } else {
189                 node.setValue(node.getValue() + " : " + bytes.toString());
190             }
191         }
192     }
193 
194     /*
195      * (non-Javadoc)
196      * 
197      * @see net.sourceforge.servletspy.IContext#invalidate()
198      */
199     public void invalidate() {
200         this.node = null;
201     }
202 
203     /*
204      * (non-Javadoc)
205      * 
206      * @see net.sourceforge.servletspy.IContext#proceed()
207      */
208     public void proceed() {
209         transformerIndex++;
210         try {
211             if (transformerIndex < transformers.length && node != null) {
212                 try {
213                     node
214                             .setDebugHint(ClassUtil.getSimpleClassName(transformers[transformerIndex].getClass())
215                                     + " -- "
216                                     + System.identityHashCode(getSubject()));
217                     transformers[transformerIndex].handle(this);
218                 } catch (InvocationTargetException e) {
219                     final Throwable throwable = e.getTargetException();
220                     handleException(throwable);
221                 } catch (Exception e) {
222                     handleException(e);
223                 }
224             }
225         } finally {
226             transformerIndex--;
227         }
228     }
229 
230     /*
231      * (non-Javadoc)
232      * 
233      * @see net.sourceforge.servletspy.IContext#setSubject(java.lang.Object)
234      */
235     public void setSubject(final Object pSubject) {
236         getIntrospectedMap().remove(this.subject);
237         if (pSubject != null) {
238             getIntrospectedMap().put(pSubject, this.getNode());
239         }
240         this.subject = pSubject;
241     }
242 
243     /*
244      * (non-Javadoc)
245      * 
246      * @see net.sourceforge.servletspy.IContext#setValue(java.lang.String)
247      */
248     public void setValue(final String value) {
249         if (getNode() == null) {
250             throw new IllegalStateException();
251         }
252         getNode().setValue(value);
253     }
254 }