1 /*
   2  * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
   3  * 
   4  * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
   5  * Virtual Machine, which is developed at Christian Doppler Laboratory on
   6  * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
   7  * contact us at <http://mevss.jku.at/> if you need additional information
   8  * or have any questions.
   9  *
  10  * This code is free software; you can redistribute it and/or modify it
  11  * under the terms of the GNU General Public License version 2 only, as
  12  * published by the Free Software Foundation.
  13  *
  14  * This code is distributed in the hope that it will be useful, but WITHOUT
  15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  17  * version 2 for more details (a copy is included in the LICENSE file that
  18  * accompanied this code).
  19  *
  20  * You should have received a copy of the GNU General Public License version
  21  * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
  22  *
  23  */ 
  24 package sun.evtracing.parser.metadata;
  25 
  26 import java.io.EOFException;
  27 import java.io.IOException;
  28 import java.io.Reader;
  29 import java.io.StringReader;
  30 
  31 public class JvmNamePrettyPrinter {
  32 
  33         public static String prettyClassName(String className, boolean compact) {
  34                 try {
  35                         Reader reader = new StringReader(className);
  36                         StringBuilder sb = new StringBuilder();
  37                         int c = peek(reader);
  38                         if (c == '[') {
  39                                 prettyPrintNextType(reader, sb, compact);
  40                         } else {
  41                                 int startLength = sb.length();
  42                                 c = reader.read();
  43                                 while (c != -1) {
  44                                         if (c == '/') {
  45                                                 if (compact) {
  46                                                         sb.setLength(startLength);
  47                                                 } else {
  48                                                         sb.append('.');
  49                                                 }
  50                                         } else {
  51                                                 sb.append((char) c);
  52                                         }
  53                                         c = reader.read();
  54                                 }
  55                         }
  56                         return sb.toString();
  57                 } catch (Exception ex) {
  58                         throw new RuntimeException(ex);
  59                 }
  60         }
  61 
  62         public static String prettyMethodName(String className, String methodName, boolean compact) {
  63                 return prettyClassName(className, compact) + "." + methodName;
  64         }
  65 
  66         public static String prettyMethodDescriptor(String className, String methodName, String signature, boolean compact) {
  67                 return prettyMethodName(className, methodName, compact) + prettyMethodSignature(signature, compact);
  68         }
  69 
  70         public static String prettyMethodSignature(String signature, boolean compact) {
  71                 StringBuilder sb = new StringBuilder();
  72                 StringReader reader = new StringReader(signature);
  73                 try {
  74                         int c = reader.read();
  75                         assert c == '(';
  76                         sb.append('(');
  77 
  78                         c = peek(reader);
  79                         if (c == -1)
  80                                 throw new EOFException("closing parenthesis");
  81 
  82                         // arguments
  83                         while (c != ')') {
  84                                 prettyPrintNextType(reader, sb, compact);
  85 
  86                                 c = peek(reader);
  87                                 if (c == -1)
  88                                         throw new EOFException("closing parenthesis");
  89 
  90                                 if (c != ')')
  91                                         sb.append(", ");
  92                         }
  93 
  94                         c = reader.read(); // consume ')'
  95 
  96                         sb.append(')');
  97 
  98                         // return type
  99                         sb.append(" : ");
 100                         prettyPrintNextType(reader, sb, compact);
 101                 } catch (Exception e) {
 102                         throw new RuntimeException("unparsable signature '" + signature + "'", e);
 103                 }
 104                 return sb.toString();
 105         }
 106 
 107         private static int peek(Reader reader) throws IOException {
 108                 int c;
 109                 reader.mark(1);
 110                 c = reader.read();
 111                 reader.reset();
 112                 return c;
 113         }
 114 
 115         private static void prettyPrintNextType(Reader reader, StringBuilder sb, boolean compact) throws Exception {
 116                 int arrayDimensions = 0;
 117                 boolean atEnd;
 118                 do {
 119                         int c = reader.read();
 120                         if (c == -1)
 121                                 throw new EOFException();
 122 
 123                         atEnd = true;
 124                         switch (c) {
 125                         case '[':
 126                                 arrayDimensions++;
 127                                 atEnd = false;
 128                                 break;
 129                         case 'B': sb.append("byte");    break;
 130                         case 'C': sb.append("char");    break;
 131                         case 'D': sb.append("double");  break;
 132                         case 'F': sb.append("float");   break;
 133                         case 'I': sb.append("int");     break;
 134                         case 'J': sb.append("long");    break;
 135                         case 'S': sb.append("short");   break;
 136                         case 'Z': sb.append("boolean"); break;
 137                         case 'V': sb.append("void");    break;
 138                         case 'L':
 139                                 int startLength = sb.length();
 140                                 do {
 141                                         c = reader.read();
 142                                         if (c == -1)
 143                                                 throw new EOFException("in class name");
 144                                         if (c != ';') {
 145                                                 if (c == '/') {
 146                                                         if (compact) {
 147                                                                 sb.setLength(startLength);
 148                                                         } else {
 149                                                                 sb.append('.');
 150                                                         }
 151                                                 } else {
 152                                                         sb.append((char) c);
 153                                                 }
 154                                         }
 155                                 } while (c != ';');
 156                                 break;
 157                         default:
 158                                 throw new Exception("invalid type '" + (char) c + "'");
 159                         }
 160                 } while (!atEnd);
 161 
 162                 for (int i = 0; i < arrayDimensions; i++) {
 163                         sb.append("[]");
 164                 }
 165         }
 166 
 167 }