001: /*
002: * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.xml.internal.bind.v2.runtime;
027:
028: import java.lang.annotation.Annotation;
029: import java.util.ArrayList;
030: import java.util.Collections;
031: import java.util.List;
032:
033: import javax.xml.bind.JAXBContext;
034: import javax.xml.bind.JAXBException;
035:
036: import com.sun.xml.internal.bind.v2.model.annotation.Locatable;
037:
038: /**
039: * Signals an incorrect use of JAXB annotations.
040: *
041: * @author Kohsuke Kawaguchi (kk@kohsuke.org)
042: * @since JAXB 2.0 EA1
043: */
044: public class IllegalAnnotationException extends JAXBException {
045:
046: /**
047: * Read-only list of {@link Location}s.
048: */
049: private final List<List<Location>> pos;
050:
051: private static final long serialVersionUID = 1L;
052:
053: public IllegalAnnotationException(String message, Locatable src) {
054: super (message);
055: pos = build(src);
056: }
057:
058: public IllegalAnnotationException(String message, Annotation src) {
059: this (message, cast(src));
060: }
061:
062: public IllegalAnnotationException(String message, Locatable src1,
063: Locatable src2) {
064: super (message);
065: pos = build(src1, src2);
066: }
067:
068: public IllegalAnnotationException(String message, Annotation src1,
069: Annotation src2) {
070: this (message, cast(src1), cast(src2));
071: }
072:
073: public IllegalAnnotationException(String message, Annotation src1,
074: Locatable src2) {
075: this (message, cast(src1), src2);
076: }
077:
078: public IllegalAnnotationException(String message, Throwable cause,
079: Locatable src) {
080: super (message, cause);
081: pos = build(src);
082: }
083:
084: private static Locatable cast(Annotation a) {
085: if (a instanceof Locatable)
086: return (Locatable) a;
087: else
088: return null;
089: }
090:
091: private List<List<Location>> build(Locatable... srcs) {
092: List<List<Location>> r = new ArrayList<List<Location>>();
093: for (Locatable l : srcs) {
094: if (l != null) {
095: List<Location> ll = convert(l);
096: if (ll != null && !ll.isEmpty())
097: r.add(ll);
098: }
099: }
100: return Collections.unmodifiableList(r);
101: }
102:
103: /**
104: * Builds a list of {@link Location}s out of a {@link Locatable}.
105: */
106: private List<Location> convert(Locatable src) {
107: if (src == null)
108: return null;
109:
110: List<Location> r = new ArrayList<Location>();
111: for (; src != null; src = src.getUpstream())
112: r.add(src.getLocation());
113: return Collections.unmodifiableList(r);
114: }
115:
116: /**
117: * Returns a read-only list of {@link Location} that indicates
118: * where in the source code the problem has happened.
119: *
120: * <p>
121: * Normally, an annotation error happens on one particular
122: * annotation, in which case this method returns a list that
123: * contains another list, which in turn contains the location
124: * information that leads to the error location
125: * (IOW, <tt>[ [pos1,pos2,...,posN] ]</tt>)
126: *
127: * <p>
128: * Sometimes, an error could occur because of two or more conflicting
129: * annotations, in which case this method returns a list
130: * that contains many lists, where each list contains
131: * the location information that leads to each of the conflicting
132: * annotations
133: * (IOW, <tt>[ [pos11,pos12,...,pos1N],[pos21,pos22,...,pos2M], ... ]</tt>)
134: *
135: * <p>
136: * Yet some other time, the runtime can fail to provide any
137: * error location, in which case this method returns an empty list.
138: * (IOW, <tt>[]</tt>). We do try hard to make sure this won't happen,
139: * so please <a href="http://jaxb.dev.java.net/">let us know</a>
140: * if you see this behavior.
141: *
142: *
143: * <h3>List of {@link Location}</h3>
144: * <p>
145: * Each error location is identified not just by one {@link Location}
146: * object, but by a sequence of {@link Location}s that shows why
147: * the runtime is led to the place of the error.
148: * This list is sorted such that the most specific {@link Location} comes
149: * to the first in the list, sort of like a stack trace.
150: *
151: * <p>
152: * For example, suppose you specify class <tt>Foo</tt> to {@link JAXBContext},
153: * <tt>Foo</tt> derives from <tt>Bar</tt>, <tt>Bar</tt> has a field <tt>pea</tt>
154: * that points to <tt>Zot</tt>, <tt>Zot</tt> contains a <tt>gum</tt>
155: * property, and this property has an errornous annotation.
156: * Then when this exception is thrown, the list of {@link Location}s
157: * will look something like
158: * <tt>[ "gum property", "Zot class", "pea property", "Bar class", "Foo class" ]</tt>
159: *
160: *
161: * @return
162: * can be empty when no source position is available,
163: * but never null. The returned list will never contain
164: * null nor length-0 {@link List}.
165: */
166: public List<List<Location>> getSourcePos() {
167: return pos;
168: }
169:
170: /**
171: * Returns the exception name, message, and related information
172: * together in one string.
173: *
174: * <p>
175: * Overriding this method (instead of {@link #printStackTrace} allows
176: * this crucial detail to show up even when this exception is nested
177: * inside other exceptions.
178: */
179: public String toString() {
180: StringBuilder sb = new StringBuilder(getMessage());
181:
182: for (List<Location> locs : pos) {
183: sb
184: .append("\n\tthis problem is related to the following location:");
185: for (Location loc : locs)
186: sb.append("\n\t\tat ").append(loc.toString());
187: }
188:
189: return sb.toString();
190: }
191: }
|