/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.jini.core.entry; import java.io.InvalidObjectException; import java.io.IOException; import java.io.PrintStream; import java.io.PrintWriter; import java.io.ObjectInputStream; /** * Thrown when one tries to get an <code>Entry</code> from a service, * but the entry is unusable (due to serialization or other errors). * Normally <code>partialEntry</code> points to an entry with as many * fields as possible filled in, with the array <code>unusableFields</code> * naming the fields that could not be deserialized and the array * <code>nestedExceptions</code> having the corresponding exception. * <p> * If the serialized <code>Entry</code> was corrupt enough that no * attempt could even be made to deserialize its fields, * <code>partialEntry</code> and <code>unusableFields</code> will be * <code>null</code>, and <code>nestedExceptions</code> will be an * array with one element that is the offending exception. This will * typically be because one or more of the classes of the <code>Entry</code> * type itself cannot be loaded. * <p> * The names in <code>unusableFields</code> can be used together with * the reflection mechanisms of <code>java.lang.reflect</code> to * examine the full state of the object. * * @author Sun Microsystems, Inc. * * @since 1.0 */ public class UnusableEntryException extends Exception { static final long serialVersionUID = -2199083666668626172L; /** * The partial entry. Fields that could not be deserialized * will be <code>null</code>. * * @serial */ public Entry partialEntry; /** * The names of the unusable fields. If the entry was entirely * unusable, <code>unusableFields</code> will be <code>null</code>. * * @serial */ public String[] unusableFields; /** * The exception that caused the failure for the corresponding * field named in unusableFields. If the entry was entirely * unusable, <code>nestedExceptions</code> will be an array with * the one exception that prevented its use. * * @serial */ public Throwable[] nestedExceptions; /** * Create an exception for the given partial entry and vectors of * bad field names/nested exception pairs. * * @param partial the Entry object on which the exception occurred * @param badFields a String array containing the bad field names * @param exceptions an array of Throwable objects associated with the * bad field names * * @throws IllegalArgumentException if <code>partial</code> is * <code>null</code> and <code>badFields</code> is not * <code>null</code> or <code>exceptions</code> does not have * exactly one element or if <code>partial</code> is * non-<code>null</code> and <code>badFields</code> and * <code>exceptions</code> are not the same length * * @throws NullPointerException if <code>partial</code> is * non-<code>null</code> and <code>badFields</code> or any * element of <code>badFields</code> is <code>null</code>, or * if <code>exceptions</code> or any element of * <code>exceptions</code> is <code>null</code> */ public UnusableEntryException(Entry partial, String[] badFields, Throwable[] exceptions) { super(); if (partial == null) { if (exceptions.length != 1) { throw new IllegalArgumentException("If partial is null " + "exceptions must have one element"); } if (badFields != null) { throw new IllegalArgumentException("If partial is null " + "badFields must be null"); } } else { if (badFields.length != exceptions.length) { throw new IllegalArgumentException("If partial is non-null " + "badFields and exceptions must have same length"); } } if (badFields != null) { for (int i=0; i<badFields.length; i++) { if (badFields[i] == null) throw new NullPointerException("badFields has a null element"); } } for (int i=0; i<exceptions.length; i++) { if (exceptions[i] == null) throw new NullPointerException("exceptions has a null element"); } partialEntry = partial; unusableFields = badFields; nestedExceptions = exceptions; } /** * Create an exception for a nested exception that prevented even an * attempt to build an entry. * * @param e a Throwable representing the nested exception * @throws NullPointerException if <code>e</code> is <code>null</code> */ public UnusableEntryException(Throwable e) { if (e == null) throw new NullPointerException("e must be non-null"); partialEntry = null; unusableFields = null; nestedExceptions = new Throwable[] { e }; } /** * @throws InvalidObjectException if: * <ul> * <li> <code>partialEntry</code> is <code>null</code> and * <code>unusableFields</code> is not <code>null</code> or * <code>nestedExceptions</code> does not have exactly one * element, * <li> if <code>partialEntry</code> is non-<code>null</code> and * <code>unusableFields</code> and * <code>nestedExceptions</code> are not the same length, * <li> if <code>partialEntry</code> is non-<code>null</code> and * <code>unusableFields</code> is <code>null</code> or * any element of <code>unusableFields</code> is * <code>null</code>, or * <li> if <code>nestedExceptions</code> or any element of * <code>nestedExceptions</code> is <code>null</code> * </ul> */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); if (partialEntry == null) { if (nestedExceptions.length != 1) { throw new InvalidObjectException("If partialEntry is null " + "nestedExceptions must have one element"); } if (unusableFields != null) { throw new InvalidObjectException("If partialEntry is null " + "unusableFields must be null"); } } else { if (unusableFields == null) throw new InvalidObjectException("unusableFields is null"); if (nestedExceptions == null) throw new InvalidObjectException("nestedExceptions is null"); if (unusableFields.length != nestedExceptions.length) { throw new InvalidObjectException("If partialEntry is non-null " + "unusableFields and nestedExceptions must have same length"); } } if (unusableFields != null) { for (int i=0; i<unusableFields.length; i++) { if (unusableFields[i] == null) throw new InvalidObjectException("unusableFields has a " + "null element"); } } for (int i=0; i<nestedExceptions.length; i++) { if (nestedExceptions[i] == null) throw new InvalidObjectException("nestedExceptions has a null " + "element"); } } /** * @throws InvalidObjectException if called */ private void readObjectNoData() throws InvalidObjectException { throw new InvalidObjectException( "UnusableEntryExceptions should always have data"); } /** * Calls {@link #printStackTrace(PrintStream) printStackTrace(System.err)}. */ public void printStackTrace() { printStackTrace(System.err); } /** * Calls {@link Exception#printStackTrace(PrintStream) * super.printStackTrace(s)} and then calls {@link * Throwable#printStackTrace(PrintStream) printStackTrace(s)} on * each exception in <code>nestedExceptions</code>. */ public void printStackTrace(PrintStream s) { synchronized (s) { super.printStackTrace(s); if (unusableFields == null) { s.println("Total unmarshalling failure, cause was:"); nestedExceptions[0].printStackTrace(s); } else { s.println("Partial unmarshalling failure"); for (int i=0; i<nestedExceptions.length; i++) { s.println(unusableFields[i] + " field could not be unmarshalled because of:"); nestedExceptions[i].printStackTrace(s); } } } } /** * Calls {@link Exception#printStackTrace(PrintWriter) * super.printStackTrace(s)} and then calls {@link * Throwable#printStackTrace(PrintWriter) printStackTrace(s)} on * each exception in <code>nestedExceptions</code>. */ public void printStackTrace(PrintWriter s) { synchronized (s) { super.printStackTrace(s); if (unusableFields == null) { s.println("Total unmarshalling failure, cause was:"); nestedExceptions[0].printStackTrace(s); } else { s.println("Partial unmarshalling failure"); for (int i=0; i<nestedExceptions.length; i++) { s.println(unusableFields[i] + " field could not be unmarshalled because of:"); nestedExceptions[i].printStackTrace(s); } } } } }