Project Report: fawkez

Packagesummary org.jcoderz.commons.util

org.jcoderz.commons.util.JaxbUtil

LineHitsNoteSource
1  /*
2   * $Id: JaxbUtil.java 1011 2008-06-16 17:57:36Z amandel $
3   *
4   * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5   *
6   * Redistribution and use in source and binary forms, with or without
7   * modification, are permitted provided that the following conditions are
8   * met:
9   *
10   *    * Redistributions of source code must retain the above copyright
11   *      notice, this list of conditions and the following disclaimer.
12   *    * Redistributions in binary form must reproduce the above
13   *      copyright notice, this list of conditions and the following
14   *      disclaimer in the documentation and/or other materials
15   *      provided with the distribution.
16   *    * Neither the name of the jCoderZ.org Project nor the names of
17   *      its contributors may be used to endorse or promote products
18   *      derived from this software without specific prior written
19   *      permission.
20   *
21   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25   * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32   */
33   package org.jcoderz.commons.util;
34  
35  import java.io.ByteArrayOutputStream;
36  import java.util.ArrayList;
37  import java.util.Collections;
38  import java.util.HashMap;
39  import java.util.List;
40  import java.util.Map;
41  import java.util.logging.Level;
42  import java.util.logging.Logger;
43  
44  import javax.xml.bind.JAXBContext;
45  import javax.xml.bind.JAXBException;
46  import javax.xml.bind.Marshaller;
47  import javax.xml.bind.Unmarshaller;
48  import javax.xml.bind.ValidationEvent;
49  import javax.xml.bind.ValidationEventHandler;
50  import javax.xml.bind.ValidationEventLocator;
51  
52  import org.jcoderz.commons.ArgumentMalformedException;
53  import org.jcoderz.commons.RteLogMessage;
54  import org.xml.sax.InputSource;
55  
56  
57  /**
58   * Utility class to simplify JAXB marshalling/unmarshalling.
59   * @author Albrecht Messner
60   */
61  public final class JaxbUtil
62  {
630    private static final Map JAXB_CONTEXT_MAP = new HashMap();
64  
65  
66     private JaxbUtil ()
670    {
68        // avoid instantiation of utility class
690    }
70  
71     /**
72      * Returns a JAXB context for the given context path. Contexts are
73      * cached in a hash map.
74      * @param contextPath the JAXB context path
75      * @return the jaxb context for the given context path
76      * @throws JAXBException if the context could not be retrieved
77      */
78     public static synchronized JAXBContext getJaxbContext (String contextPath)
79           throws JAXBException
80     {
810       JAXBContext ctx = (JAXBContext) JAXB_CONTEXT_MAP.get(contextPath);
820       if (ctx == null)
83        {
840          ctx = JAXBContext.newInstance(contextPath);
850(1)         JAXB_CONTEXT_MAP.put(contextPath, ctx);
86        }
870       return ctx;
88     }
89  
90     /**
91      * Unmarshals the given InputSource and returns the unmarshalled object
92      * along with the validation event collector.
93      * @param data the data to unmarshal
94      * @param ctxPath the context path from which the JAXBContext is created
95      *       to create an unmarshaller
96      * @return the unmarshalled object along with its validation events
97      * @throws JAXBException if unmarshalling or validation fails.
98      */
99     public static UnmarshalResult unmarshal (InputSource data, String ctxPath)
100           throws JAXBException
101     {
1020       final JAXBContext ctx = getJaxbContext(ctxPath);
1030       return unmarshal(data, ctx);
104     }
105  
106     /**
107      * Unmarshals the given InputSource and returns the unmarshalled object
108      * along with the validation event collector.
109      * @param data the data to unmarshal
110      * @param ctx the JAXBContext from which the unmarshaller should be
111      *       retrieved
112      * @return the unmarshalled object along with its validation events
113      * @throws JAXBException if unmarshalling or validation fails.
114      */
115     public static UnmarshalResult unmarshal (InputSource data, JAXBContext ctx)
116           throws JAXBException
117     {
1180       final Unmarshaller unmarsh = ctx.createUnmarshaller();
1190(2)      unmarsh.setValidating(true);
1200       final ValidationEventCollector evtHandler
121              = new ValidationEventCollector();
1220       unmarsh.setEventHandler(evtHandler);
1230       final Object parsedData = unmarsh.unmarshal(data);
1240       return new UnmarshalResult(parsedData, evtHandler);
125     }
126  
127     /**
128      * Serializes (marshals) a given JAXB object and returns the result as
129      * byte array, along with the validation events collected during
130      * marshalling.
131      * @param data the object to marshal
132      * @param contextPath the context path to retrieve the corresponding JAXB
133      *       context for.
134      * @return the marshalled object and marshalling events
135      * @throws JAXBException if marshalling or validation fails.
136      */
137     public static MarshalResult marshal (Object data, String contextPath)
138           throws JAXBException
139     {
1400       final JAXBContext ctx = getJaxbContext(contextPath);
1410       return marshal(data, ctx);
142     }
143  
144     /**
145      * Serializes (marshals) a given JAXB object and returns the result as
146      * byte array, along with the validation events collected during
147      * marshalling.
148      * @param data the object to marshal
149      * @param ctx the JAXBContext from which the unmarshaller can be retrieved.
150      * @return the marshalled object and marshalling events
151      * @throws JAXBException if marshalling or validation fails.
152      */
153     public static MarshalResult marshal (Object data, JAXBContext ctx)
154           throws JAXBException
155     {
1560       final Marshaller marsh = ctx.createMarshaller();
1570       final ValidationEventCollector evtHandler
158              = new ValidationEventCollector();
1590       marsh.setEventHandler(evtHandler);
1600       final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
1610       marsh.marshal(data, outStream);
1620       final MarshalResult result
163              = new MarshalResult(outStream.toByteArray(), evtHandler);
1640(3)      return result;
165     }
166  
167     /**
168      * Holds the Result of an unmarshal operation.
169      * @author Albrecht Messner
170      */
171     public static class UnmarshalResult
172     {
173        private final Object mParsedData;
174        private final ValidationEventCollector mValidationEvents;
175  
176        UnmarshalResult (Object parsedData, ValidationEventCollector evtHandler)
1770       {
1780          mParsedData = parsedData;
1790          mValidationEvents = evtHandler;
1800       }
181  
182        /**
183         * Returns the parsed (unmarshalled) object.
184         * @return the parsed (unmarshalled) object.
185         */
186        public Object getParsedData ()
187        {
1880          return mParsedData;
189        }
190  
191        /**
192         * Returns the validation events of the unmarshal operation.
193         * @return the validation events of the unmarshal operation.
194         */
195        public ValidationEventCollector getValidationEvents ()
196        {
1970          return mValidationEvents;
198        }
199     }
200  
201     /**
202      * Holds the Result of an Marshal operation.
203      * @author Albrecht Messner
204      */
205     public static class MarshalResult
206     {
207        private final byte[] mMarshalledData;
208        private final ValidationEventCollector mValidationEvents;
209  
210        MarshalResult (byte[] marshalledData, ValidationEventCollector evtHandler)
2110       {
2120          mMarshalledData = marshalledData;
2130          mValidationEvents = evtHandler;
2140       }
215  
216        /**
217         * Returns the marshalled object.
218         * @return the marshalled object.
219         */
220        public byte[] getMarshalledData ()
221        {
2220(4)(5)         return mMarshalledData;
223        }
224  
225        /**
226         * Returns the validation events of the marshal operation.
227         * @return the validation events of the marshal operation.
228         */
229        public ValidationEventCollector getValidationEvents ()
230        {
2310          return mValidationEvents;
232        }
233     }
234  
235     /**
236      * Validation handler for JAXB.
237      *
238      * @author Michael Griffel
239      */
2400    public static class ValidationEventCollector
241           implements ValidationEventHandler
242     {
2430       private static final String CLASSNAME
244              = ValidationEventCollector.class.getName();
245  
2460       private static final Logger logger = Logger.getLogger(CLASSNAME);
247  
2480       private final List mEvents = new ArrayList();
249  
250        /**
251         * Returns all the collected errors and warnings or an empty list
252         * if there weren't any. The result is an unmodifiable list.
253         *
254         * @return all the collected errors and warnings or an empty list
255         *      if there weren't any. The result is an unmodifiable list.
256         */
257        public List getEvents ()
258        {
2590          return Collections.unmodifiableList(mEvents);
260        }
261  
262        /**
263         * Clear all collected errors and warnings.
264         */
265        public void reset ()
266        {
2670          mEvents.clear();
2680       }
269  
270        /**
271         * Returns true if this event collector contains at least one
272         * ValidationEvent.
273         *
274         * @return true if this event collector contains at least one
275         *         ValidationEvent, false otherwise
276         */
277        public boolean hasEvents ()
278        {
2790(6)         return mEvents.size() != 0;
280        }
281  
282        /** {@inheritDoc} */
283        public boolean handleEvent (ValidationEvent event)
284        {
2850          final String methodName = "handleEvent";
2860          if (logger.isLoggable(Level.FINER))
287           {
2880             logger.entering(CLASSNAME, methodName, event);
2890             logger.finer("Event details: "
290                    + eventToString(new StringBuffer(), event));
291           }
292  
2930          mEvents.add(event);
294  
2950          final boolean doContinue
296                 = event.getSeverity() != ValidationEvent.FATAL_ERROR;
297  
2980          if (logger.isLoggable(Level.FINER))
299           {
3000             logger.exiting(CLASSNAME, methodName, String.valueOf(doContinue));
301           }
3020          return doContinue;
303        }
304  
305        /**
306         * Returns a summary of the validation events as String.
307         * @return a summary of the validation events as String.
308         */
309        public String toString ()
310        {
3110          final StringBuffer sb = new StringBuffer();
3120          for (int i = 0; i < mEvents.size(); ++i)
313           {
3140             sb.append('[');
3150             sb.append(i + 1);
3160             sb.append('/');
3170             sb.append(mEvents.size());
3180             sb.append("] ");
3190             final ValidationEvent e = (ValidationEvent) mEvents.get(i);
3200             eventToString(sb, e);
321           }
3220          return sb.toString().trim();
323        }
324  
325        private StringBuffer eventToString (
326              final StringBuffer sb, final ValidationEvent e)
327        {
3280          appendLocator(sb, e.getLocator());
329  
3300          if (e.getLinkedException() != null)
331           {
3320             appendLinkedException(sb, e);
333           }
334           else
335           {
3360             sb.append(e.getMessage());
337           }
3380          appendSpace(sb);
339  
3400          return sb;
341        }
342  
343        private void appendLinkedException (final StringBuffer sb,
344              final ValidationEvent e)
345        {
3460          final String causeMessage = e.getLinkedException().getMessage();
3470          if (!e.getMessage().equals(causeMessage))
348           {
3490             if (e.getLinkedException() instanceof ArgumentMalformedException)
350              {
3510                final ArgumentMalformedException ame
352                       = (ArgumentMalformedException) e.getLinkedException();
3530                sb.append("The Argument ");
3540                sb.append(getParameter(
355                       ame, RteLogMessage.ArgumentMalformed.PARAM_ARGUMENT_NAME));
3560                sb.append(" with the value '");
3570                sb.append(getParameter(ame,
358                       RteLogMessage.ArgumentMalformed.PARAM_ARGUMENT_VALUE));
3590                sb.append("' is malformed. ");
3600                sb.append(getParameter(
361                       ame, RteLogMessage.ArgumentMalformed.PARAM_HINT));
3620             }
363              else
364              {
3650                sb.append(e.getMessage());
3660                if (causeMessage != null)
367                 {
3680                   sb.append(" Cause: ");
3690                   sb.append(causeMessage);
370                 }
371              }
372           }
373           else
374           {
3750             sb.append(e.getMessage());
376           }
3770       }
378  
379        private void appendLocator (final StringBuffer sb,
380              ValidationEventLocator locator)
381        {
3820          if (locator != null)
383           {
3840             if (locator.getObject() != null)
385              {
3860               sb.append("Object: ");
3870               sb.append(locator.getObject());
3880               appendSpace(sb);
389              }
3900             if (locator.getNode() != null)
391              {
3920               sb.append("Node: ");
3930               sb.append(locator.getObject());
3940               appendSpace(sb);
395              }
3960             if (locator.getOffset() >= 0)
397              {
3980                sb.append("Offset: ");
3990                sb.append(locator.getOffset());
4000                appendSpace(sb);
401              }
402           }
4030       }
404  
405        /** Simply appends a spece to the given StringBuffer. */
406        private final StringBuffer appendSpace (final StringBuffer sb)
407        {
4080          return sb.append(' ');
409        }
410  
411        private String getParameter (ArgumentMalformedException ex, String name)
412        {
4130(7)         final List parameters = ex.getParameter(name);
414           final String result;
4150          if (parameters != null)
416           {
4170             result = (String) parameters.get(0);
418           }
419           else
420           {
4210             result = "";
422           }
4230          return result;
424        }
425     }
426  
427  }

Findings in this File

w (1) 85 : 0 class org.jcoderz.commons.util.JaxbUtil defines static field that appears to allow memory bloat
d (2) 119 : 14 [deprecation] setValidating(boolean) in javax.xml.bind.Unmarshaller has been deprecated
w (3) 164 : 0 method org.jcoderz.commons.util.JaxbUtil.marshal(Object, JAXBContext) stores return result in local before immediately returning it
w (4) 222 : 0 org.jcoderz.commons.util.JaxbUtil$MarshalResult.getMarshalledData() may expose internal representation by returning JaxbUtil$MarshalResult.mMarshalledData
d (5) 222 : 10 Returning 'mMarshalledData' may expose an internal array.
d (6) 279 : 17 Substitute calls to size() == 0 (or size() != 0) with calls to isEmpty()
w (7) 413 : 0 method org.jcoderz.commons.util.JaxbUtil$ValidationEventCollector.getParameter(ArgumentMalformedException, String) needlessly defines parameter with concrete classes