001/*
002 * oauth2-oidc-sdk
003 *
004 * Copyright 2012-2020, Connect2id Ltd and contributors.
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
007 * this file except in compliance with the License. You may obtain a copy of the
008 * License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software distributed
013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
015 * specific language governing permissions and limitations under the License.
016 */
017
018package com.nimbusds.openid.connect.sdk.federation.api;
019
020
021import net.jcip.annotations.Immutable;
022import net.minidev.json.JSONObject;
023
024import com.nimbusds.oauth2.sdk.ErrorObject;
025import com.nimbusds.oauth2.sdk.ParseException;
026import com.nimbusds.oauth2.sdk.http.HTTPResponse;
027import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
028
029
030/**
031 * Federation API error.
032 *
033 * <ul>
034 *     <li>OpenID Connect Federation 1.0, section 6.4.
035 * </ul>
036 */
037@Immutable
038public class FederationAPIError extends ErrorObject {
039        
040        
041        private static final long serialVersionUID = 2116693118039606386L;
042        
043        
044        /**
045         * The operation type.
046         */
047        private final OperationType operationType;
048        
049        
050        /**
051         * Creates a new federation API error.
052         *
053         * @param operationType The operation type, {@code null} if not
054         *                      specified.
055         * @param code          The error code, {@code null} if not specified.
056         * @param description   The error description, {@code null} if not
057         *                      specified.
058         */
059        public FederationAPIError(final OperationType operationType, final String code, final String description) {
060                this(operationType, code, description, 0);
061        }
062        
063        
064        /**
065         * Creates a new federation API error.
066         *
067         * @param operationType  The operation type, {@code null} if not
068         *                       specified.
069         * @param code           The error code, {@code null} if not specified.
070         * @param description    The error description, {@code null} if not
071         *                       specified.
072         * @param httpStatusCode The HTTP status code, zero if not specified.
073         */
074        public FederationAPIError(final OperationType operationType,
075                                  final String code,
076                                  final String description,
077                                  final int httpStatusCode) {
078                super(code, description, httpStatusCode);
079                this.operationType = operationType;
080        }
081        
082        
083        /**
084         * Returns the operation type.
085         *
086         * @return The operation type, {@code null} if not specified.
087         */
088        public OperationType getOperationType() {
089                return operationType;
090        }
091        
092        
093        /**
094         * Returns a copy of this federation API error with the specified HTTP
095         * status code.
096         *
097         * @param httpStatusCode The HTTP status code, zero if not specified.
098         *
099         * @return The new federation API error.
100         */
101        public FederationAPIError withStatusCode(final int httpStatusCode) {
102                return new FederationAPIError(getOperationType(), getCode(), getDescription(), httpStatusCode);
103        }
104        
105        
106        @Override
107        public JSONObject toJSONObject() {
108                JSONObject jsonObject = super.toJSONObject();
109                if (getOperationType() != null) {
110                        jsonObject.put("operation", getOperationType().getValue());
111                }
112                return jsonObject;
113        }
114        
115        
116        /**
117         * Parses a federation API error object from the specified JSON object.
118         *
119         * @param jsonObject The JSON object to parse. Must not be
120         *                   {@code null}.
121         *
122         * @return The federation API error object.
123         */
124        public static FederationAPIError parse(final JSONObject jsonObject) {
125                ErrorObject errorObject = ErrorObject.parse(jsonObject);
126                OperationType operationType = null;
127                try {
128                        operationType = new OperationType(JSONObjectUtils.getString(jsonObject, "operation"));
129                } catch (ParseException e) {
130                        // ignore
131                }
132                return new FederationAPIError(operationType, errorObject.getCode(), errorObject.getDescription());
133        }
134        
135        
136        /**
137         * Parses a federation API error object from the specified HTTP
138         * response.
139         *
140         * @param httpResponse The HTTP response to parse. Must not be
141         *                     {@code null}.
142         *
143         * @return The federation API error object.
144         */
145        public static FederationAPIError parse(final HTTPResponse httpResponse) {
146                JSONObject jsonObject;
147                try {
148                        jsonObject = httpResponse.getContentAsJSONObject();
149                } catch (ParseException e) {
150                        jsonObject = new JSONObject();
151                }
152                return FederationAPIError.parse(jsonObject).withStatusCode(httpResponse.getStatusCode());
153        }
154}