aoqi@0: /* aoqi@0: * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.xml.internal.bind.v2.runtime; aoqi@0: aoqi@0: import java.lang.annotation.Annotation; aoqi@0: import java.util.ArrayList; aoqi@0: import java.util.Collections; aoqi@0: import java.util.List; aoqi@0: aoqi@0: import javax.xml.bind.JAXBContext; aoqi@0: import javax.xml.bind.JAXBException; aoqi@0: aoqi@0: import com.sun.xml.internal.bind.v2.model.annotation.Locatable; aoqi@0: aoqi@0: /** aoqi@0: * Signals an incorrect use of JAXB annotations. aoqi@0: * aoqi@0: * @author Kohsuke Kawaguchi (kk@kohsuke.org) aoqi@0: * @since JAXB 2.0 EA1 aoqi@0: */ aoqi@0: public class IllegalAnnotationException extends JAXBException { aoqi@0: aoqi@0: /** aoqi@0: * Read-only list of {@link Location}s. aoqi@0: */ aoqi@0: private final List> pos; aoqi@0: aoqi@0: private static final long serialVersionUID = 1L; aoqi@0: aoqi@0: public IllegalAnnotationException(String message, Locatable src) { aoqi@0: super(message); aoqi@0: pos = build(src); aoqi@0: } aoqi@0: aoqi@0: public IllegalAnnotationException(String message, Annotation src) { aoqi@0: this(message,cast(src)); aoqi@0: } aoqi@0: aoqi@0: public IllegalAnnotationException(String message, Locatable src1, Locatable src2) { aoqi@0: super(message); aoqi@0: pos = build(src1,src2); aoqi@0: } aoqi@0: aoqi@0: public IllegalAnnotationException(String message, Annotation src1, Annotation src2) { aoqi@0: this(message,cast(src1),cast(src2)); aoqi@0: } aoqi@0: aoqi@0: public IllegalAnnotationException(String message, Annotation src1, Locatable src2) { aoqi@0: this(message,cast(src1),src2); aoqi@0: } aoqi@0: aoqi@0: public IllegalAnnotationException(String message, Throwable cause, Locatable src) { aoqi@0: super(message, cause); aoqi@0: pos = build(src); aoqi@0: } aoqi@0: aoqi@0: private static Locatable cast(Annotation a) { aoqi@0: if(a instanceof Locatable) aoqi@0: return (Locatable)a; aoqi@0: else aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: private List> build(Locatable... srcs) { aoqi@0: List> r = new ArrayList>(); aoqi@0: for( Locatable l : srcs ) { aoqi@0: if(l!=null) { aoqi@0: List ll = convert(l); aoqi@0: if(ll!=null && !ll.isEmpty()) aoqi@0: r.add(ll); aoqi@0: } aoqi@0: } aoqi@0: return Collections.unmodifiableList(r); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Builds a list of {@link Location}s out of a {@link Locatable}. aoqi@0: */ aoqi@0: private List convert(Locatable src) { aoqi@0: if(src==null) return null; aoqi@0: aoqi@0: List r = new ArrayList(); aoqi@0: for( ; src!=null; src=src.getUpstream()) aoqi@0: r.add(src.getLocation()); aoqi@0: return Collections.unmodifiableList(r); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * Returns a read-only list of {@link Location} that indicates aoqi@0: * where in the source code the problem has happened. aoqi@0: * aoqi@0: *

aoqi@0: * Normally, an annotation error happens on one particular aoqi@0: * annotation, in which case this method returns a list that aoqi@0: * contains another list, which in turn contains the location aoqi@0: * information that leads to the error location aoqi@0: * (IOW, [ [pos1,pos2,...,posN] ]) aoqi@0: * aoqi@0: *

aoqi@0: * Sometimes, an error could occur because of two or more conflicting aoqi@0: * annotations, in which case this method returns a list aoqi@0: * that contains many lists, where each list contains aoqi@0: * the location information that leads to each of the conflicting aoqi@0: * annotations aoqi@0: * (IOW, [ [pos11,pos12,...,pos1N],[pos21,pos22,...,pos2M], ... ]) aoqi@0: * aoqi@0: *

aoqi@0: * Yet some other time, the runtime can fail to provide any aoqi@0: * error location, in which case this method returns an empty list. aoqi@0: * (IOW, []). We do try hard to make sure this won't happen, aoqi@0: * so please let us know aoqi@0: * if you see this behavior. aoqi@0: * aoqi@0: * aoqi@0: *

List of {@link Location}

aoqi@0: *

aoqi@0: * Each error location is identified not just by one {@link Location} aoqi@0: * object, but by a sequence of {@link Location}s that shows why aoqi@0: * the runtime is led to the place of the error. aoqi@0: * This list is sorted such that the most specific {@link Location} comes aoqi@0: * to the first in the list, sort of like a stack trace. aoqi@0: * aoqi@0: *

aoqi@0: * For example, suppose you specify class Foo to {@link JAXBContext}, aoqi@0: * Foo derives from Bar, Bar has a field pea aoqi@0: * that points to Zot, Zot contains a gum aoqi@0: * property, and this property has an errornous annotation. aoqi@0: * Then when this exception is thrown, the list of {@link Location}s aoqi@0: * will look something like aoqi@0: * [ "gum property", "Zot class", "pea property", "Bar class", "Foo class" ] aoqi@0: * aoqi@0: * aoqi@0: * @return aoqi@0: * can be empty when no source position is available, aoqi@0: * but never null. The returned list will never contain aoqi@0: * null nor length-0 {@link List}. aoqi@0: */ aoqi@0: public List> getSourcePos() { aoqi@0: return pos; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Returns the exception name, message, and related information aoqi@0: * together in one string. aoqi@0: * aoqi@0: *

aoqi@0: * Overriding this method (instead of {@link #printStackTrace} allows aoqi@0: * this crucial detail to show up even when this exception is nested aoqi@0: * inside other exceptions. aoqi@0: */ aoqi@0: public String toString() { aoqi@0: StringBuilder sb = new StringBuilder(getMessage()); aoqi@0: aoqi@0: for( List locs : pos ) { aoqi@0: sb.append("\n\tthis problem is related to the following location:"); aoqi@0: for( Location loc : locs ) aoqi@0: sb.append("\n\t\tat ").append(loc.toString()); aoqi@0: } aoqi@0: aoqi@0: return sb.toString(); aoqi@0: } aoqi@0: }