org.neo4j.server.rest.repr.ExceptionRepresentation Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [https://neo4j.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.neo4j.server.rest.repr;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.neo4j.graphdb.ConstraintViolationException;
import org.neo4j.internal.helpers.collection.IterableWrapper;
import org.neo4j.kernel.api.exceptions.Status;
import org.neo4j.server.rest.Neo4jError;
public class ExceptionRepresentation extends MappingRepresentation {
private final List errors = new LinkedList<>();
private boolean includeLegacyRepresentation;
public ExceptionRepresentation(Throwable exception) {
this(exception, true);
}
public ExceptionRepresentation(Throwable exception, boolean includeLegacyRepresentation) {
super(RepresentationType.EXCEPTION);
this.errors.add(new Neo4jError(statusCode(exception), exception));
this.includeLegacyRepresentation = includeLegacyRepresentation;
}
@Override
protected void serialize(MappingSerializer serializer) {
// For legacy reasons, this actually serializes into two separate formats - the old format, which simply
// serializes a single exception, and the new format which serializes multiple errors and provides simple
// status codes.
if (includeLegacyRepresentation) {
renderWithLegacyFormat(errors.get(0).cause(), serializer);
}
renderWithStatusCodeFormat(serializer);
}
private void renderWithStatusCodeFormat(MappingSerializer serializer) {
serializer.putList("errors", ErrorEntryRepresentation.list(errors));
}
private static void renderWithLegacyFormat(Throwable exception, MappingSerializer serializer) {
String message = exception.getMessage();
if (message != null) {
serializer.putString("message", message);
}
serializer.putString("exception", exception.getClass().getSimpleName());
serializer.putString("fullname", exception.getClass().getName());
StackTraceElement[] trace = exception.getStackTrace();
if (trace != null) {
Collection lines = new ArrayList<>(trace.length);
for (StackTraceElement element : trace) {
if (element.toString().matches(".*(jetty|jersey|sun\\.reflect|mortbay|javax\\.servlet).*")) {
continue;
}
lines.add(element.toString());
}
serializer.putList("stackTrace", ListRepresentation.string(lines));
}
Throwable cause = exception.getCause();
if (cause != null) {
serializer.putMapping("cause", new ExceptionRepresentation(cause));
}
}
private static class ErrorEntryRepresentation extends MappingRepresentation {
private final Neo4jError error;
ErrorEntryRepresentation(Neo4jError error) {
super("error-entry");
this.error = error;
}
@Override
protected void serialize(MappingSerializer serializer) {
serializer.putString("code", error.status().code().serialize());
serializer.putString("message", error.getMessage());
}
public static ListRepresentation list(Collection errors) {
return new ListRepresentation(
"error-list", new IterableWrapper(errors) {
@Override
protected ErrorEntryRepresentation underlyingObjectToObject(Neo4jError error) {
return new ErrorEntryRepresentation(error);
}
});
}
}
private static Status statusCode(Throwable current) {
while (current != null) {
if (current instanceof Status.HasStatus) {
return ((Status.HasStatus) current).status();
}
if (current instanceof ConstraintViolationException) {
return Status.Schema.ConstraintValidationFailed;
}
current = current.getCause();
}
return Status.General.UnknownError;
}
}