/*
* Copyright 2003-2012 Yusuke Yamamoto
*
* 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 samurai.core;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.*;
public abstract class ThreadDump implements Serializable {
private List<StackLine> lockList = null;
private StackLine blockedLine = null;
private final List<StackLine> stackLines = new ArrayList<StackLine>();
private final String HEADER;
private static final long serialVersionUID = -7984606567041592064L;
private final String NAME;
protected String STACK_RANGE;
protected boolean IS_BLOCKED;
protected boolean IS_IDLE;
protected boolean IS_DAEMON;
protected boolean IS_BLOCKING;
private Pattern conditionCatchPtn = Pattern.compile("(?<= *)[^\"]+$");
private final String CONDITION;
public ThreadDump(String header) {
this.HEADER = header;
//extract thread name
int headerBeginIndex = getHeader().indexOf("\"") + 1;
int headerEndIndex = getHeader().indexOf("\"", headerBeginIndex);
NAME = getHeader().substring(headerBeginIndex, headerEndIndex);
Matcher m = conditionCatchPtn.matcher(this.HEADER);
m.find();
this.CONDITION = m.group();
}
public final String getHeader() {
return this.HEADER;
}
public String getCondition() {
return this.CONDITION;
}
public final List<StackLine> getStackLines() {
return this.stackLines;
}
public final int size() {
return getStackLines().size();
}
/*package*/
abstract void addStackLine(String line);
protected void addStackLine(StackLine stackLine) {
getStackLines().add(stackLine);
if (stackLine.isTryingToGetLock()) {
blockedLine = stackLine;
}
if (stackLine.isHoldingLock()) {
// this.IS_BLOCKING = true;
if (null == lockList) {
lockList = new ArrayList<StackLine>();
}
lockList.add(stackLine);
}
}
public String getBlockerId() {
if (null != blockedLine) {
return this.blockedLine.getBlockerId();
}
return null;
}
/*package*/ void setBlockerId(String id) {
this.blockedLine.setBlockerId(id);
}
public List<StackLine> getLockedLines() {
return lockList;
}
public String getBlockedObjectId() {
if (null != blockedLine) {
return blockedLine.getLockedObjectId();
} else {
return null;
}
}
/**
* returns the thread's name.
*
* @return name
*/
public final String getName() {
return NAME;
}
public final StackLine getLine(int i) {
return getStackLines().get(i);
}
/**
* test if thread is a daemon thread.
*
* @return if the thread is a daemon thread.
*/
public boolean isDaemon() {
return IS_DAEMON;
}
/**
* returns the thread's stack range.
*
* @return name
*/
public String getStackRange() {
return this.STACK_RANGE;
}
public boolean isBlocked() {
return IS_BLOCKED;
}
public boolean isIdle() {
return IS_IDLE;
}
public abstract String getId();
public final boolean equals(Object obj) {
boolean isEqual = false;
if (null != obj && obj instanceof ThreadDump) {
ThreadDump that = (ThreadDump) obj;
if (that == this) {
isEqual = true;
} else {
if (that.size() == this.size()) {
List thatList = that.getStackLines();
List thisList = this.getStackLines();
isEqual = true;
for (int i = 0; i < this.size(); i++) {
if (!thisList.get(i).equals(thatList.get(i))) {
isEqual = false;
break;
}
}
}
}
}
return isEqual;
}
public String getHeaderParameter(String name) {
int index = getCondition().indexOf(name + "=");
int paramStart;
int paramEnd;
if (-1 != index) {
//Sun
paramStart = index + name.length() + 1;
paramEnd = getCondition().indexOf(" ", paramStart);
} else if (-1 != (index = getCondition().indexOf(name + ": "))) {
//JRockit viking
paramStart = index + name.length() + 2;
paramEnd = getCondition().indexOf(" ", paramStart);
} else if (-1 != (index = getCondition().indexOf(name + ":"))) {
//IBM and JRockit Ariane & Dragon
paramStart = index + name.length() + 1;
paramEnd = getCondition().indexOf(" ", paramStart);
int tmp = getCondition().indexOf(")", paramStart);
if (tmp != -1 && tmp < paramEnd) {
paramEnd = tmp;
}
tmp = getCondition().indexOf(",", paramStart);
if (tmp != -1 && tmp < paramEnd) {
paramEnd = tmp;
}
} else {
return "";
}
if (-1 != paramEnd) {
return getCondition().substring(paramStart, paramEnd);
} else {
return getCondition().substring(paramStart);
}
}
private boolean deadLocked = false;
public boolean isDeadLocked() {
return this.deadLocked;
}
public boolean isBlocking() {
return this.IS_BLOCKING;
}
/*package*/ void setDeadLocked(boolean deadLocked) {
this.deadLocked = deadLocked;
}
/*package*/ void setBlocking(boolean blocking) {
this.IS_BLOCKING = blocking;
}
}