001/*
002 * (C) Copyright 2006-2020 Nuxeo (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 NuxeoException addInfo(String info) {
103        if (infos == null) {
104            infos = new LinkedList<>();
105        }
106        infos.addFirst(info);
107        return this;
108    }
109
110    /**
111     * Gets the information added to this exception.
112     * <p>
113     * The list is returned in the reverse order than that of the calls to {@link #addInfo}, i.e., the last added
114     * information is first in the list.
115     *
116     * @return the information list
117     * @since 7.4
118     */
119    public List<String> getInfos() {
120        return infos == null ? Collections.emptyList() : infos;
121    }
122
123    /**
124     * Gets the original message passed to the constructor, without additional information added.
125     *
126     * @since 7.4
127     */
128    public String getOriginalMessage() {
129        return super.getMessage();
130    }
131
132    @Override
133    public String getMessage() {
134        String message = getOriginalMessage();
135        if (infos == null) {
136            return message;
137        } else {
138            StringBuilder sb = new StringBuilder();
139            for (String info : infos) {
140                sb.append(info);
141                sb.append(", ");
142            }
143            sb.append(message);
144            return sb.toString();
145        }
146    }
147
148    /**
149     * Gets the HTTP status code mapped to this exception.
150     *
151     * @since 9.3
152     */
153    public int getStatusCode() {
154        return statusCode;
155    }
156
157}