/*******************************************************************************
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.apache.kato.hprof;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import org.apache.kato.hprof.datalayer.HProfFile;
import org.apache.kato.hprof.datalayer.IHProfRecord;
import org.apache.kato.hprof.datalayer.ILoadClassHProfRecord;
import org.apache.kato.hprof.datalayer.IUTF8HProfRecord;
public class HProfRecordFormatter {
private static final String hexChars="0123456789ABCDEF";
private HProfFile prof=null;
HashMap<Long, Integer> utf8s=null;
public HProfRecordFormatter(HProfFile prof, HashMap<Long, Integer> utf8s) {
this.prof=prof;
this.utf8s=utf8s;
}
public String formatData(IHProfRecord o) {
int tag=o.getTag();
switch(tag) {
case 0x01 : return formatUTF8Data((IUTF8HProfRecord)o);
case 0x02: return formatLoadCLass((ILoadClassHProfRecord)o);
case 0x04: return "Frame";
case 0x05: return "Trace";
case 0x0A: return "Thread Start";
case 0x0B: return "Thread End";
case 0x0C: return "HeapDump";
case 0x0E: return "Settings";
}
return "";
}
public String formatLoadCLass(ILoadClassHProfRecord o) {
long id=o.getClassNameID();
long classID=o.getClassObjectID();
long serialNo=o.getClassSerialNumber();
long stackSerial=o.getStackTraceSerialNumber();
String className="";
if(utf8s.containsKey(id)) {
int ref=utf8s.get(id);
className=getName(ref);
if(className==null) className="";
else className="("+className+")";
}
return "classNameID="+toHex(id)+className+" objectid="+toHex(classID)+" serialNo="+toHex(serialNo)+" stackSerial="+toHex(stackSerial);
}
public String getName(Long id) {
if(utf8s.containsKey(id)==false) return null;
int ref=utf8s.get(id);
return getName(ref);
}
private String getName(int ref) {
IHProfRecord record=prof.getRecord(ref);
if(record instanceof IUTF8HProfRecord) {
IUTF8HProfRecord utf8rec=(IUTF8HProfRecord) record;
return utf8rec.getAsString();
}
return null;
}
public static String toHex(long v) {
return "0x"+Long.toHexString(v);
}
public static String formatUTF8Data(IUTF8HProfRecord utf8Record) {
try {
return new String(utf8Record.getCharacters(),"UTF-8");
} catch (UnsupportedEncodingException e) {
return "Error converting data "+e.toString();
}
}
public static String getTagName(IHProfRecord o) {
int tag=o.getTag();
switch(tag) {
case 0x01 : return "UTF8";
case 0x02: return "LoadClass";
case 0x04: return "Frame";
case 0x05: return "Trace";
case 0x0A: return "Thread started";
case 0x0B: return "Thread ending";
case 0x0C: return "HeapDump";
case 0x0E: return "Settings";
}
return o.getClass().getName();
}
public static String toHex(byte[] bytes) {
if(bytes==null) return "<no data>";
return toHex(bytes,0,bytes.length);
}
public static String toHex(byte[] bytes, int start, int length) {
if(bytes==null) return "<no data>";
if(bytes.length<start) return "<bad start>";
StringBuilder builder=new StringBuilder();
for(int i=0;i<length;i++) {
int index=i+start;
if(index>=bytes.length) break;
builder.append(toHex(bytes[index]));
builder.append(" ");
}
return new String(builder);
}
private static String toHex(byte b) {
int value= (int) b & 0xFF;
int top=value >> 4;
int bottom= value & 0x0F;
return ""+hexChars.charAt(top)+hexChars.charAt(bottom);
}
public static String toHex(byte[] bytes, int start, int length, int packet) {
if(bytes==null) return "<no data>";
if(bytes.length<start) return "<bad start>";
StringBuilder builder=new StringBuilder();
int c=packet;
for(int i=0;i<length;i++) {
int index=i+start;
if(index>=bytes.length) break;
builder.append(toHex(bytes[index]));
builder.append(" ");
c--;
if(c==0) {
builder.append("\n");
c=packet;
}
}
return new String(builder);
}
public static String toPrintableText(byte[] bytes) {
if(bytes==null) return "<no data>";
StringBuilder builder=new StringBuilder();
for(int i=0;i<bytes.length;i++) {
char c=(char) bytes[i];
if(Character.isLetterOrDigit(c)) {
builder.append(c);
}
else {
builder.append('.');
}
}
return new String(builder);
}
}