1/* 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.xml.internal.bind.v2.runtime; 27 28import java.lang.annotation.Annotation; 29import java.util.ArrayList; 30import java.util.Collections; 31import java.util.List; 32 33import javax.xml.bind.JAXBContext; 34import javax.xml.bind.JAXBException; 35 36import com.sun.xml.internal.bind.v2.model.annotation.Locatable; 37 38/** 39 * Signals an incorrect use of JAXB annotations. 40 * 41 * @author Kohsuke Kawaguchi (kk@kohsuke.org) 42 * @since JAXB 2.0 EA1 43 */ 44public class IllegalAnnotationException extends JAXBException { 45 46 /** 47 * Read-only list of {@link Location}s. 48 */ 49 private final List<List<Location>> pos; 50 51 private static final long serialVersionUID = 1L; 52 53 public IllegalAnnotationException(String message, Locatable src) { 54 super(message); 55 pos = build(src); 56 } 57 58 public IllegalAnnotationException(String message, Annotation src) { 59 this(message,cast(src)); 60 } 61 62 public IllegalAnnotationException(String message, Locatable src1, Locatable src2) { 63 super(message); 64 pos = build(src1,src2); 65 } 66 67 public IllegalAnnotationException(String message, Annotation src1, Annotation src2) { 68 this(message,cast(src1),cast(src2)); 69 } 70 71 public IllegalAnnotationException(String message, Annotation src1, Locatable src2) { 72 this(message,cast(src1),src2); 73 } 74 75 public IllegalAnnotationException(String message, Throwable cause, Locatable src) { 76 super(message, cause); 77 pos = build(src); 78 } 79 80 private static Locatable cast(Annotation a) { 81 if(a instanceof Locatable) 82 return (Locatable)a; 83 else 84 return null; 85 } 86 87 private List<List<Location>> build(Locatable... srcs) { 88 List<List<Location>> r = new ArrayList<List<Location>>(); 89 for( Locatable l : srcs ) { 90 if(l!=null) { 91 List<Location> ll = convert(l); 92 if(ll!=null && !ll.isEmpty()) 93 r.add(ll); 94 } 95 } 96 return Collections.unmodifiableList(r); 97 } 98 99 /** 100 * Builds a list of {@link Location}s out of a {@link Locatable}. 101 */ 102 private List<Location> convert(Locatable src) { 103 if(src==null) return null; 104 105 List<Location> r = new ArrayList<Location>(); 106 for( ; src!=null; src=src.getUpstream()) 107 r.add(src.getLocation()); 108 return Collections.unmodifiableList(r); 109 } 110 111 112 113 /** 114 * Returns a read-only list of {@link Location} that indicates 115 * where in the source code the problem has happened. 116 * 117 * <p> 118 * Normally, an annotation error happens on one particular 119 * annotation, in which case this method returns a list that 120 * contains another list, which in turn contains the location 121 * information that leads to the error location 122 * (IOW, {@code [ [pos1,pos2,...,posN] ]}) 123 * 124 * <p> 125 * Sometimes, an error could occur because of two or more conflicting 126 * annotations, in which case this method returns a list 127 * that contains many lists, where each list contains 128 * the location information that leads to each of the conflicting 129 * annotations 130 * (IOW, {@code [ [pos11,pos12,...,pos1N],[pos21,pos22,...,pos2M], ... ]}) 131 * 132 * <p> 133 * Yet some other time, the runtime can fail to provide any 134 * error location, in which case this method returns an empty list. 135 * (IOW, {@code []}). We do try hard to make sure this won't happen, 136 * so please <a href="http://jaxb.dev.java.net/">let us know</a> 137 * if you see this behavior. 138 * 139 * 140 * <h3>List of {@link Location}</h3> 141 * <p> 142 * Each error location is identified not just by one {@link Location} 143 * object, but by a sequence of {@link Location}s that shows why 144 * the runtime is led to the place of the error. 145 * This list is sorted such that the most specific {@link Location} comes 146 * to the first in the list, sort of like a stack trace. 147 * 148 * <p> 149 * For example, suppose you specify class {@code Foo} to {@link JAXBContext}, 150 * {@code Foo} derives from {@code Bar}, {@code Bar} has a field {@code pea} 151 * that points to {@code Zot}, {@code Zot} contains a {@code gum} 152 * property, and this property has an errornous annotation. 153 * Then when this exception is thrown, the list of {@link Location}s 154 * will look something like 155 * {@code [ "gum property", "Zot class", "pea property", "Bar class", "Foo class" ]} 156 * 157 * 158 * @return 159 * can be empty when no source position is available, 160 * but never null. The returned list will never contain 161 * null nor length-0 {@link List}. 162 */ 163 public List<List<Location>> getSourcePos() { 164 return pos; 165 } 166 167 /** 168 * Returns the exception name, message, and related information 169 * together in one string. 170 * 171 * <p> 172 * Overriding this method (instead of {@link #printStackTrace} allows 173 * this crucial detail to show up even when this exception is nested 174 * inside other exceptions. 175 */ 176 public String toString() { 177 StringBuilder sb = new StringBuilder(getMessage()); 178 179 for( List<Location> locs : pos ) { 180 sb.append("\n\tthis problem is related to the following location:"); 181 for( Location loc : locs ) 182 sb.append("\n\t\tat ").append(loc.toString()); 183 } 184 185 return sb.toString(); 186 } 187} 188