Home » apache-openjpa-1.1.0-source » org.apache.openjpa » util » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements.  See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership.  The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License.  You may obtain a copy of the License at
    9    *
   10    * http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    * Unless required by applicable law or agreed to in writing,
   13    * software distributed under the License is distributed on an
   14    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15    * KIND, either express or implied.  See the License for the
   16    * specific language governing permissions and limitations
   17    * under the License.    
   18    */
   19   package org.apache.openjpa.util;
   20   
   21   import java.io.ObjectOutputStream;
   22   import java.io.OutputStream;
   23   import java.io.PrintStream;
   24   import java.io.PrintWriter;
   25   import java.io.Serializable;
   26   import java.util.Collection;
   27   import java.util.Iterator;
   28   
   29   import org.apache.openjpa.conf.OpenJPAVersion;
   30   import org.apache.openjpa.enhance.PersistenceCapable;
   31   import org.apache.openjpa.lib.util.J2DoPrivHelper;
   32   import org.apache.openjpa.lib.util.JavaVersions;
   33   
   34   /**
   35    * Utility methods for externalizing and handling exceptions.
   36    *
   37    * @author Marc Prud'hommeaux
   38    * @since 0.2.5
   39    * @nojavadoc
   40    */
   41   public class Exceptions {
   42   
   43       public static final Throwable[] EMPTY_THROWABLES = new Throwable[0];
   44   
   45       static final String SEP = J2DoPrivHelper.getLineSeparator();
   46   
   47       private static final OutputStream DEV_NULL = new OutputStream() {
   48           public void write(int b) {
   49           }
   50       };
   51   
   52       /**
   53        * Test to see if the specified object will be able to be serialized. This
   54        * will check if the object implements {@link Serializable}, and if so,
   55        * will try to perform an actual serialization. This is in case the object
   56        * has fields which, in turn, are not serializable.
   57        *
   58        * @param ob the object to test
   59        * @return true if the object will be able to be serialized
   60        */
   61       private static boolean isSerializable(Object ob) {
   62           if (!(ob instanceof Serializable))
   63               return false;
   64   
   65           // don't serialize persistent objects exceptions to prevent
   66           // reading in all the state
   67           if (!ImplHelper.isManagedType(null, ob.getClass()))
   68               return false;
   69   
   70           // now do an actual test to see if we will be
   71           // able to perform the serialization
   72           try {
   73               new ObjectOutputStream(DEV_NULL).writeObject(ob);
   74               return true;
   75           } catch (Throwable t) {
   76               return false;
   77           }
   78       }
   79   
   80       /**
   81        * Safely stringify the given object.
   82        */
   83       public static String toString(Object ob) {
   84           if (ob == null)
   85               return "null";
   86   
   87           // don't take oid of new objects since it can cause a flush if auto-inc
   88           // and the id is meaningless anyway
   89           Object oid = getObjectId(ob);
   90   
   91           if (oid != null) {
   92               if (oid instanceof Id)
   93                   return oid.toString();
   94               return ob.getClass().getName() + "-" + oid.toString();
   95           }
   96   
   97           if (ImplHelper.isManagedType(null, ob.getClass())) {
   98               // never call toString() on a PersistenceCapable, since
   99               // it may access persistent fields; fall-back to using
  100               // the standard object stringification mechanism. New
  101               // instances that use proxying (property-access instances,
  102               // for example) that were created with the 'new' keyword
  103               // will not end up in this code, which is ok since they
  104               // don't do lazy loading anyways, so they will stringify
  105               // safely.
  106               return ob.getClass().getName() + "@"
  107                   + Integer.toHexString(System.identityHashCode(ob));
  108           }
  109   
  110           try {
  111               String s = ob.toString();
  112               if (s.indexOf(ob.getClass().getName()) == -1)
  113                   s += " [" + ob.getClass().getName() + "]";
  114               return s;
  115           } catch (Throwable t) {
  116               return ob.getClass().getName();
  117           }
  118       }
  119   
  120       /**
  121        * Safely stringify the given objects.
  122        */
  123       public static String toString(Collection failed) {
  124           StringBuffer buf = new StringBuffer();
  125           buf.append("[");
  126           for (Iterator itr = failed.iterator(); itr.hasNext();) {
  127               buf.append(Exceptions.toString(itr.next()));
  128               if (itr.hasNext())
  129                   buf.append(", ");
  130           }
  131           buf.append("]");
  132           return buf.toString();
  133       }
  134   
  135       /**
  136        * Stringify the given exception.
  137        */
  138       public static String toString(ExceptionInfo e) {
  139           int type = e.getType();
  140           StringBuffer buf = new StringBuffer();
  141           buf.append("<").
  142               append(OpenJPAVersion.VERSION_ID).
  143               append(' ').
  144               append(e.isFatal() ? "fatal " : "nonfatal ").
  145               append (type == ExceptionInfo.GENERAL ? "general error" :
  146                   type == ExceptionInfo.INTERNAL ? "internal error" :
  147                   type == ExceptionInfo.STORE ? "store error" :
  148                   type == ExceptionInfo.UNSUPPORTED ? "unsupported error" :
  149                   type == ExceptionInfo.USER ? "user error" :
  150                   (type + " error")).
  151               append("> ");
  152           buf.append(e.getClass().getName()).append(": ").
  153               append(e.getMessage());
  154           Object failed = e.getFailedObject();
  155           if (failed != null)
  156               buf.append(SEP).append("FailedObject: ").
  157                   append(toString(failed));
  158           return buf.toString();
  159       }
  160   
  161       /**
  162        * Print the stack trace of the exception's nested throwables.
  163        */
  164       public static void printNestedThrowables(ExceptionInfo e, PrintStream out) {
  165           // if this is Java 1.4 and there is exactly a single
  166           // exception, then defer to 1.4's behavior of printing
  167           // out the result of getCause(). This deferral happens in
  168           // the calling code.
  169           Throwable[] nested = e.getNestedThrowables();
  170           int i = (JavaVersions.VERSION >= 4) ? 1 : 0;
  171           if (i < nested.length) {
  172               out.println("NestedThrowables:");
  173               for (; i < nested.length; i++)
  174                   // guard against a nasty null in the array
  175                   if (nested[i] != null)
  176                       nested[i].printStackTrace(out);
  177           }
  178       }
  179   
  180       /**
  181        * Print the stack trace of the exception's nested throwables.
  182        */
  183       public static void printNestedThrowables(ExceptionInfo e, PrintWriter out) {
  184           // if this is Java 1.4 and there is exactly a single
  185           // exception, then defer to 1.4's behavior of printing
  186           // out the result of getCause(). This deferral happens in
  187           // the calling code.
  188           Throwable[] nested = e.getNestedThrowables();
  189           int i = (JavaVersions.VERSION >= 4) ? 1 : 0;
  190           if (i < nested.length) {
  191               out.println("NestedThrowables:");
  192               for (; i < nested.length; i++)
  193                   // guard against a nasty null in the array
  194                   if (nested[i] != null)
  195                       nested[i].printStackTrace(out);
  196           }
  197       }
  198   
  199       /**
  200        * Convert the specified failed object into a serializable
  201        * object for when we are serializing an Exception. It will
  202        * try the following:
  203        * <ul>
  204        * <li>if the object can be serialized, return the object itself</li>
  205        * <li>if the object has a serializable oid, return the oid</li>
  206        * <li>if the object has a non-serializable oid, return the oid's
  207        * toString and the object class</li>
  208        * <li>return the object's toString</li>
  209        * </ul>
  210        *
  211        * @param ob the object to convert
  212        * @return some serialized representation of the object
  213        */
  214       public static Object replaceFailedObject(Object ob) {
  215           if (ob == null)
  216               return null;
  217           if (isSerializable(ob))
  218               return ob;
  219   
  220           // don't take oid of new objects since it can cause a flush if auto-inc
  221           // and the id is meaningless anyway
  222           Object oid = getObjectId(ob);
  223           if (oid != null && isSerializable(oid))
  224               return oid;
  225   
  226           // last ditch: stringify the object
  227           return toString(ob);
  228       }
  229   
  230       /**
  231        * Convert the specified throwables into a serialzable array. If
  232        * any of the nested throwables cannot be serialized, they will
  233        * be converted into a Exception with the original message.
  234        */
  235       public static Throwable[] replaceNestedThrowables(Throwable[] nested) {
  236           if (nested == null || nested.length == 0)
  237               return nested;
  238           if (isSerializable(nested))
  239               return nested;
  240   
  241           Throwable[] newNested = new Throwable[nested.length];
  242           for (int i = 0; i < nested.length; i++) {
  243               if (isSerializable(nested[i]))
  244                   newNested[i] = nested[i];
  245               else
  246                   // guard against a nasty null in the array by using valueOf
  247                   // instead of toString to prevent throwing yet another 
  248                   // exception
  249                   newNested[i] = new Exception(String.valueOf(nested[i]));
  250           }
  251           return newNested;
  252       }
  253   
  254       /**
  255        * Return the object id for <code>ob</code> if it has one, or
  256        * <code>null</code> otherwise.
  257        */
  258       private static Object getObjectId(Object ob) {
  259           if (!ImplHelper.isManageable(ob))
  260               return null;
  261   
  262           PersistenceCapable pc = ImplHelper.toPersistenceCapable(ob, null);
  263           if (pc == null || pc.pcIsNew())
  264               return null;
  265           else
  266               return pc.pcFetchObjectId();
  267   	}
  268   }

Save This Page
Home » apache-openjpa-1.1.0-source » org.apache.openjpa » util » [javadoc | source]