/*******************************************************************************
* Copyright (c) 2010, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.orion.server.core;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.json.JSONException;
import org.json.JSONObject;
/**
* A status that also incorporates an HTTP response code. This status is suitable
* for throwing an exception where the appropriate HTTP response for that failure
* is specified.
*/
public class ServerStatus extends Status {
/**
* A property defining an optional status object indicating the cause
* of the exception.
*/
// private static final String PROP_CAUSE = "Cause"; //$NON-NLS-1$
/**
* An integer status code. The value is specific to the component returning
* the exception.
*/
static final String PROP_CODE = "Code"; //$NON-NLS-1$
/**
* A detailed human readable error message string.
*/
public static final String PROP_DETAILED_MESSAGE = "DetailedMessage"; //$NON-NLS-1$
/**
* The id of the OSGi bundle where the error originated.
*/
public static final String PROP_BUNDLE_ID = "BundleId"; //$NON-NLS-1$
/**
* The integer HTTP response code.
*/
static final String PROP_HTTP_CODE = "HttpCode"; //$NON-NLS-1$
/**
* A high level error message string, suitable for display to a user.
*/
public static final String PROP_MESSAGE = "Message"; //$NON-NLS-1$
/**
* A property containing JSON object with data needed to handle exception
*/
static final String JSON_DATA = "JsonData"; //$NON-NLS-1$
/**
* A property defining a URL of a page with further details about the
* exception and how it can be resolved.
*/
// private static final String PROP_SEE_ALSO = "SeeAlso"; //$NON-NLS-1$
/**
* A string representing the status severity. The value is one of the
* <code>SEVERITY_*</code> constants defined in this class.
*/
static final String PROP_SEVERITY = "Severity"; //$NON-NLS-1$
static final String SEVERITY_CANCEL = "Cancel"; //$NON-NLS-1$
static final String SEVERITY_ERROR = "Error"; //$NON-NLS-1$
static final String SEVERITY_INFO = "Info"; //$NON-NLS-1$
static final String SEVERITY_OK = "Ok"; //$NON-NLS-1$
static final String SEVERITY_WARNING = "Warning"; //$NON-NLS-1$
private int httpCode;
private JSONObject jsonData;
/**
* Converts a status into a server status.
*/
public static ServerStatus convert(IStatus status) {
int httpCode = 200;
if (status.getSeverity() == IStatus.ERROR || status.getSeverity() == IStatus.CANCEL)
httpCode = 500;
return convert(status, httpCode);
}
/**
* Converts a status into a server status.
*/
public static ServerStatus convert(IStatus status, int httpCode) {
if (status instanceof ServerStatus)
return (ServerStatus) status;
return new ServerStatus(status, httpCode);
}
/**
* Returns a server status from a given JSON representation as produced
* by the {@link #toJSON()} method.
* @param string The string representation
* @return The status
* @throws JSONException If the provided string is not valid JSON representation of a status
*/
public static ServerStatus fromJSON(String string) throws JSONException {
JSONObject object = new JSONObject(string);
int httpCode = object.getInt(PROP_HTTP_CODE);
int code = object.getInt(PROP_CODE);
String message = object.getString(PROP_MESSAGE);
int severity = fromSeverityString(object.getString(PROP_SEVERITY));
String pluginId = object.optString(PROP_BUNDLE_ID);
if (pluginId == null || pluginId.length() == 0)
pluginId = ServerConstants.PI_SERVER_CORE;
String detailMessage = object.optString(PROP_DETAILED_MESSAGE, null);
Exception cause = detailMessage == null ? null : new Exception(detailMessage);
JSONObject jsonData = object.optJSONObject(JSON_DATA);
return new ServerStatus(new Status(severity, pluginId, code, message, cause), httpCode, jsonData);
}
public ServerStatus(int severity, int httpCode, String message, Throwable exception) {
super(severity, ServerConstants.PI_SERVER_CORE, message, exception);
this.httpCode = httpCode;
}
public ServerStatus(int severity, int httpCode, String message, JSONObject jsonData, Throwable exception) {
super(severity, ServerConstants.PI_SERVER_CORE, message, exception);
this.httpCode = httpCode;
this.jsonData = jsonData;
}
public ServerStatus(IStatus status, int httpCode) {
super(status.getSeverity(), status.getPlugin(), status.getCode(), status.getMessage(), status.getException());
this.httpCode = httpCode;
}
public ServerStatus(IStatus status, int httpCode, JSONObject jsonData) {
super(status.getSeverity(), status.getPlugin(), status.getCode(), status.getMessage(), status.getException());
this.httpCode = httpCode;
this.jsonData = jsonData;
}
/**
* Returns the HTTP response code associated with this status.
* @return the HTTP response code associated with this status.
*/
public int getHttpCode() {
return httpCode;
}
/**
* Returns the JSON data associated with this status. May be
* <code>null</code> if no additional data is available.
* @return the JSON data associated with this status.
*/
public JSONObject getJsonData() {
return jsonData;
}
private String getSeverityString() {
//note the severity string should not be translated
switch (getSeverity()) {
case IStatus.ERROR :
return SEVERITY_ERROR;
case IStatus.WARNING :
return SEVERITY_WARNING;
case IStatus.INFO :
return SEVERITY_INFO;
case IStatus.CANCEL :
return SEVERITY_CANCEL;
case IStatus.OK :
return SEVERITY_OK;
}
return null;
}
static int fromSeverityString(String s) {
if (SEVERITY_ERROR.equals(s)) {
return ERROR;
} else if (SEVERITY_WARNING.equals(s)) {
return WARNING;
} else if (SEVERITY_INFO.equals(s)) {
return INFO;
} else if (SEVERITY_CANCEL.equals(s)) {
return CANCEL;
}
return OK;
}
/**
* Returns a JSON representation of this status object. The resulting
* object can be converted back into a ServerStatus instance using the
* {@link #fromJSON(String)} factory method.
* @return A JSON representation of this status.
*/
public JSONObject toJSON() {
JSONObject result = new JSONObject();
try {
result.put(PROP_HTTP_CODE, httpCode);
result.put(PROP_CODE, getCode());
result.put(PROP_MESSAGE, getMessage());
result.put(PROP_BUNDLE_ID, getPlugin());
result.put(PROP_SEVERITY, getSeverityString());
if (jsonData != null)
result.put(JSON_DATA, jsonData);
Throwable exception = getException();
if (exception != null)
result.put(PROP_DETAILED_MESSAGE, exception.getMessage());
//Could also include "SeeAlso" and "Cause"
} catch (JSONException e) {
//can only happen if the key is null
}
return result;
}
}