001/*
002 * (C) Copyright 2006-2015 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Bogdan Stefanescu
018 *     Florent Guillaume
019 */
020package org.nuxeo.ecm.core.api;
021
022import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
023
024import java.util.Collections;
025import java.util.LinkedList;
026import java.util.List;
027
028/**
029 * The most generic exception thrown by the Nuxeo.
030 * <p>
031 * It can be used to provide enriched information on the exception catch path, without re-wrapping:
032 *
033 * <pre>
034 * try {
035 *     doSomething(id);
036 * } catch (NuxeoException e) {
037 *     e.addInfo("Failed to do something with document id: " + id);
038 *     throw e;
039 * }
040 * </pre>
041 */
042public class NuxeoException extends RuntimeException {
043
044    private static final long serialVersionUID = 1L;
045
046    private LinkedList<String> infos;
047
048    protected int statusCode = SC_INTERNAL_SERVER_ERROR;
049
050    public NuxeoException() {
051    }
052
053    /**
054     * @since 9.3
055     */
056    public NuxeoException(int statusCode) {
057        this.statusCode = statusCode;
058    }
059
060    public NuxeoException(String message) {
061        super(message);
062    }
063
064    /**
065     * @since 9.3
066     */
067    public NuxeoException(String message, int statusCode) {
068        super(message);
069        this.statusCode = statusCode;
070    }
071
072    public NuxeoException(String message, Throwable cause) {
073        super(message, cause);
074    }
075
076    /**
077     * @since 9.3
078     */
079    public NuxeoException(String message, Throwable cause, int statusCode) {
080        super(message, cause);
081        this.statusCode = statusCode;
082    }
083
084    public NuxeoException(Throwable cause) {
085        super(cause);
086    }
087
088    /**
089     * @since 9.3
090     */
091    public NuxeoException(Throwable cause, int statusCode) {
092        super(cause);
093        this.statusCode = statusCode;
094    }
095
096    /**
097     * Adds information to this exception, to be returned with the message.
098     *
099     * @param info the information
100     * @since 7.4
101     */
102    public void addInfo(String info) {
103        if (infos == null) {
104            infos = new LinkedList<>();
105        }
106        infos.addFirst(info);
107    }
108
109    /**
110     * Gets the information added to this exception.
111     * <p>
112     * The list is returned in the reverse order than that of the calls to {@link #addInfo}, i.e., the last added
113     * information is first in the list.
114     *
115     * @return the information list
116     * @since 7.4
117     */
118    public List<String> getInfos() {
119        return infos == null ? Collections.emptyList() : infos;
120    }
121
122    /**
123     * Gets the original message passed to the constructor, without additional information added.
124     *
125     * @since 7.4
126     */
127    public String getOriginalMessage() {
128        return super.getMessage();
129    }
130
131    @Override
132    public String getMessage() {
133        String message = getOriginalMessage();
134        if (infos == null) {
135            return message;
136        } else {
137            StringBuilder sb = new StringBuilder();
138            for (String info : infos) {
139                sb.append(info);
140                sb.append(", ");
141            }
142            sb.append(message);
143            return sb.toString();
144        }
145    }
146
147    /**
148     * Gets the HTTP status code mapped to this exception.
149     *
150     * @since 9.3
151     */
152    public int getStatusCode() {
153        return statusCode;
154    }
155
156}