1 /*
   2  * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.net.http;
  27 
  28 import java.util.Locale;
  29 
  30 /**
  31  * -Djava.net.HttpClient.log=
  32  *          errors,requests,headers,
  33  *          frames[:type:type2:..],content,ssl,trace
  34  *
  35  * Any of errors, requests, headers or content are optional.
  36  *
  37  * Other handlers may be added. All logging is at level INFO
  38  *
  39  * Logger name is "java.net.http.HttpClient"
  40  */
  41 // implements System.Logger in order to be skipped when printing the caller's
  42 // information
  43 abstract class Log implements System.Logger {
  44 
  45     static final String logProp = "java.net.http.HttpClient.log";
  46 
  47     public static final int OFF = 0;
  48     public static final int ERRORS = 0x1;
  49     public static final int REQUESTS = 0x2;
  50     public static final int HEADERS = 0x4;
  51     public static final int CONTENT = 0x8;
  52     public static final int FRAMES = 0x10;
  53     public static final int SSL = 0x20;
  54     public static final int TRACE = 0x40;
  55     static int logging;
  56 
  57     // Frame types: "control", "data", "window", "all"
  58     public static final int CONTROL = 1; // all except DATA and WINDOW_UPDATES
  59     public static final int DATA = 2;
  60     public static final int WINDOW_UPDATES = 4;
  61     public static final int ALL = CONTROL| DATA | WINDOW_UPDATES;
  62     static int frametypes;
  63 
  64     static final System.Logger logger;
  65 
  66     static {
  67         String s = Utils.getNetProperty(logProp);
  68         if (s == null) {
  69             logging = OFF;
  70         } else {
  71             String[] vals = s.split(",");
  72             for (String val : vals) {
  73                 switch (val.toLowerCase(Locale.US)) {
  74                     case "errors":
  75                         logging |= ERRORS;
  76                         break;
  77                     case "requests":
  78                         logging |= REQUESTS;
  79                         break;
  80                     case "headers":
  81                         logging |= HEADERS;
  82                         break;
  83                     case "content":
  84                         logging |= CONTENT;
  85                         break;
  86                     case "ssl":
  87                         logging |= SSL;
  88                         break;
  89                     case "trace":
  90                         logging |= TRACE;
  91                         break;
  92                     case "all":
  93                         logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS|TRACE|SSL;
  94                         break;
  95                 }
  96                 if (val.startsWith("frames")) {
  97                     logging |= FRAMES;
  98                     String[] types = val.split(":");
  99                     if (types.length == 1) {
 100                         frametypes = CONTROL | DATA | WINDOW_UPDATES;
 101                     } else {
 102                         for (String type : types) {
 103                             switch (type.toLowerCase()) {
 104                                 case "control":
 105                                     frametypes |= CONTROL;
 106                                     break;
 107                                 case "data":
 108                                     frametypes |= DATA;
 109                                     break;
 110                                 case "window":
 111                                     frametypes |= WINDOW_UPDATES;
 112                                     break;
 113                                 case "all":
 114                                     frametypes = ALL;
 115                                     break;
 116                             }
 117                         }
 118                     }
 119                 }
 120             }
 121         }
 122         if (logging != OFF) {
 123             logger = System.getLogger("java.net.http.HttpClient");
 124         } else {
 125             logger = null;
 126         }
 127     }
 128 
 129     static boolean errors() {
 130         return (logging & ERRORS) != 0;
 131     }
 132 
 133     static boolean requests() {
 134         return (logging & REQUESTS) != 0;
 135     }
 136 
 137     static boolean headers() {
 138         return (logging & HEADERS) != 0;
 139     }
 140 
 141     static boolean trace() {
 142         return (logging & TRACE) != 0;
 143     }
 144 
 145     static boolean ssl() {
 146         return (logging & SSL) != 0;
 147     }
 148 
 149     static boolean frames() {
 150         return (logging & FRAMES) != 0;
 151     }
 152 
 153     static void logError(String s, Object... s1) {
 154         if (errors())
 155             logger.log(Level.INFO, "ERROR: " + s, s1);
 156     }
 157 
 158     static void logError(Throwable t) {
 159         if (errors()) {
 160             String s = Utils.stackTrace(t);
 161             logger.log(Level.INFO, "ERROR: " + s);
 162         }
 163     }
 164 
 165     static void logSSL(String s, Object... s1) {
 166         if (ssl())
 167             logger.log(Level.INFO, "SSL: " + s, s1);
 168     }
 169 
 170     static void logTrace(String s, Object... s1) {
 171         if (trace()) {
 172             String format = "TRACE: " + s;
 173             logger.log(Level.INFO, format, s1);
 174         }
 175     }
 176 
 177     static void logRequest(String s, Object... s1) {
 178         if (requests())
 179             logger.log(Level.INFO, "REQUEST: " + s, s1);
 180     }
 181 
 182     static void logResponse(String s, Object... s1) {
 183         if (requests())
 184             logger.log(Level.INFO, "RESPONSE: " + s, s1);
 185     }
 186 
 187     static void logHeaders(String s, Object... s1) {
 188         if (headers())
 189             logger.log(Level.INFO, "HEADERS: " + s, s1);
 190     }
 191 // START HTTP2
 192     static boolean loggingFrame(Class<? extends Http2Frame> clazz) {
 193         if (frametypes == ALL) {
 194             return true;
 195         }
 196         if (clazz == DataFrame.class) {
 197             return (frametypes & DATA) != 0;
 198         } else if (clazz == WindowUpdateFrame.class) {
 199             return (frametypes & WINDOW_UPDATES) != 0;
 200         } else {
 201             return (frametypes & CONTROL) != 0;
 202         }
 203     }
 204 
 205     static void logFrames(Http2Frame f, String direction) {
 206         if (frames() && loggingFrame(f.getClass())) {
 207             logger.log(Level.INFO, "FRAME: " + direction + ": " + f.toString());
 208         }
 209     }
 210 
 211     // not instantiable
 212     private Log() {}
 213 
 214 // END HTTP2
 215 }