001package com.nimbusds.common.config;
002
003
004import java.util.Properties;
005import javax.mail.internet.ContentType;
006
007import com.thetransactioncompany.util.PropertyParseException;
008import com.thetransactioncompany.util.PropertyRetriever;
009import org.apache.logging.log4j.LogManager;
010import org.apache.logging.log4j.Logger;
011
012
013/**
014 * JSON-RPC 2.0 web API configuration. Connect2id web services with additional
015 * API configuration properties can extend this class.
016 *
017 * <p>The configuration is stored as public fields which become immutable 
018 * (final) after their initialisation.
019 *
020 * <p>Property keys: [prefix]*
021 */
022public class JSONRPC2WebAPIConfiguration implements LoggableConfiguration {
023
024
025        /**
026         * The value of the HTTP "Content-Type" header for the JSON-RPC 2.0 
027         * responses.
028         *
029         * <p>Typically set to {@code application/json;charset=utf-8} or to 
030         * {@code text/plain;charset=utf-8} to support browser CORS requests.
031         * 
032         * <p>Note that the charset must always be defined and set to
033         * {@code utf-8}.
034         *
035         * <p>Property key: [prefix]responseContentType
036         */
037        public final String responseContentType;
038
039
040        /**
041         * The default response content type.
042         */
043        public static final String DEFAULT_RESPONSE_CONTENT_TYPE = 
044                "application/json; charset=utf-8";
045        
046        
047        /**
048         * <p>If {@code true} the web service will expose exception details to
049         * clients in the JSON-RPC 2.0 error "data" field. Use this setting for
050         * debugging purposes or if the web clients are trusted.
051         * 
052         * <p>If {@code false} the web service will not provide any exception
053         * details in JSON-RPC 2.0 errors. Use this setting if the web clients 
054         * are not trusted or if they don't need to know details about 
055         * encountered exceptions.
056         *
057         * <p>Property key: [prefix]exposeExceptions
058         */
059        public final boolean exposeExceptions;
060
061
062        /**
063         * The default expose exceptions policy.
064         */
065        public static final boolean DEFAULT_EXPOSE_EXCEPTIONS = false;
066        
067        
068        /**
069         * If {@code true} enables reporting of request processing time by 
070         * appending a non-standard "xProcTime" attribute to the JSON-RPC 2.0 
071         * responses.
072         *
073         * <p>Intended for debugging and testing purposes. Disabled by default 
074         * to prevent parse exceptions by clients which don't allow unexpected 
075         * JSON attributes in the JSON-RPC 2.0 response messages.
076         *
077         * <p>Property key: [prefix]reportRequestProcTime
078         */
079        public final boolean reportRequestProcTime;
080
081
082        /**
083         * The default request processing time reporting.
084         */
085        public static final boolean DEFAULT_REPORT_REQUEST_PROC_TIME = false;
086
087
088        /**
089         * Creates a JSON-RPC 2.0 web API configuration from the specified 
090         * properties.
091         *
092         * <p>Mandatory properties:
093         *
094         * <ul>
095         *     <li>none
096         * </ul>
097         *
098         * <p>Optional properties, with defaults:
099         *
100         * <ul>
101         *     <li>[prefix]responseContentType = application/json; charset=utf-8
102         *     <li>[prefix]exposeExceptions = false
103         *     <li>[prefix]reportRequestProcTime =  false
104         *     <li>
105         * </ul>
106         *
107         * @param prefix The properties prefix. Must not be {@code null}.
108         * @param props  The properties. Must not be {@code null}.
109         *
110         * @throws PropertyParseException On a missing or invalid property.
111         */
112        public JSONRPC2WebAPIConfiguration(final String prefix, final Properties props)
113                throws PropertyParseException {
114
115                PropertyRetriever pr = new PropertyRetriever(props);
116                
117                // Response content type
118                ContentType mime;
119
120                try {
121                        mime = new ContentType(pr.getOptString(prefix + "responseContentType", 
122                                                               DEFAULT_RESPONSE_CONTENT_TYPE));
123
124                } catch (javax.mail.internet.ParseException e) {
125
126                        throw new PropertyParseException("Invalid Content-Type header value", 
127                                                         prefix + "responseContentType");
128                }
129
130                if (mime.getParameter("charset") == null)
131                        mime.setParameter("charset", "utf-8");
132
133                else if (! mime.getParameter("charset").equalsIgnoreCase("utf-8"))
134                        throw new PropertyParseException("The charset parameter of " + 
135                                                          prefix + "responseContentType must be UTF-8");
136
137                responseContentType = mime.toString();
138
139                // Expose exceptions
140                exposeExceptions = pr.getOptBoolean(prefix + "exposeExceptions", 
141                                                    DEFAULT_EXPOSE_EXCEPTIONS);
142
143                // xProcTime reporting
144                reportRequestProcTime = pr.getOptBoolean(prefix + "reportRequestProcTime", 
145                                                         DEFAULT_REPORT_REQUEST_PROC_TIME);
146        }
147
148
149        /**
150         * Logs the configuration details at INFO level.
151         */
152        @Override
153        public void log() {
154
155                Logger log = LogManager.getLogger(LOG_CATEGORY);
156
157                log.info("[CM2100] Web API HTTP response Content-Type: {}", responseContentType);
158                log.info("[CM2101] Web API exposes exception details: {}", exposeExceptions);
159                log.info("[CM2102] Web API reports request processing time: {}", reportRequestProcTime);
160        }
161}