package er.profiling.delegates;
import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import com.webobjects.appserver.WOContext;
import com.webobjects.appserver.WOElement;
import com.webobjects.appserver.WOMessage;
import com.webobjects.appserver.WORequest;
import com.webobjects.appserver.WOResponse;
import er.profiling.PFProfiler;
import er.profiling.PFStatsNode;
public class PFMarkup implements PFProfiler.Delegate {
private static Pattern _tagPattern = Pattern.compile("<[a-zA-Z]+[ />]?", Pattern.MULTILINE);
private static final String _marker = "~~PROFILER_MARKER~~";
private boolean _markupEnabled;
private ThreadLocal<List<MarkerStats>> _markerList = new ThreadLocal<List<MarkerStats>>();
private Field _contentField;
public void requestStarted(WORequest request) {
// just trigger markup enablement on heatEnabled right now
_markupEnabled = PFHeatMap.isHeatEnabled();
_markerList.set(new LinkedList<>());
try {
_contentField = WOMessage.class.getDeclaredField("_content");
_contentField.setAccessible(true);
} catch (Throwable t) {
throw new RuntimeException("Unable to load the _content field of WOMessage.", t);
}
}
public void requestEnded(WORequest request) {
// DO NOTHING
}
public void responseEnded(WOResponse response, WOContext context) {
// DO NOTHING
}
protected static void append(Object content, String str) {
if (content instanceof StringBuffer) {
((StringBuffer) content).append(str);
} else if (content instanceof StringBuilder) {
((StringBuilder) content).append(str);
} else {
throw new IllegalArgumentException("Don't know how to append to '" + content + "'.");
}
}
protected static void insert(Object content, int index, String str) {
if (content instanceof StringBuffer) {
((StringBuffer) content).insert(index, str);
} else if (content instanceof StringBuilder) {
((StringBuilder) content).insert(index, str);
} else {
throw new IllegalArgumentException("Don't know how to insert into '" + content + "'.");
}
}
protected static void replace(Object content, int start, int end, String str) {
if (content instanceof StringBuffer) {
((StringBuffer) content).replace(start, end, str);
} else if (content instanceof StringBuilder) {
((StringBuilder) content).replace(start, end, str);
} else {
throw new IllegalArgumentException("Don't know how to replace strings in '" + content + "'.");
}
}
protected static int indexOf(Object content, String str, int fromIndex) {
if (content instanceof StringBuffer) {
return ((StringBuffer) content).indexOf(str, fromIndex);
} else if (content instanceof StringBuilder) {
return ((StringBuilder) content).indexOf(str, fromIndex);
} else {
throw new IllegalArgumentException("Don't know how to insert into '" + content + "'.");
}
}
protected static boolean regionMatches(CharSequence str, int toffset, String other, int ooffset, int len) {
int to = toffset;
int po = ooffset;
// Note: toffset, ooffset, or len might be near -1>>>1.
int count = str.length();
int otherCount = other.length();
if ((ooffset < 0) || (toffset < 0) || (toffset > (long) count - len) || (ooffset > (long) otherCount - len)) {
return false;
}
while (len-- > 0) {
if (str.charAt(to++) != other.charAt(po++)) {
return false;
}
}
return true;
}
public void willAppendToResponse(WOElement element, WOResponse response, WOContext context) {
if (_markupEnabled) {
try {
MarkerStats ms = new MarkerStats();
ms._stats = PFProfiler.currentStats();
Object content = _contentField.get(response);
if (content != null) {
ms._index = ((CharSequence) content).length();
append(content, PFMarkup._marker);
}
_markerList.get().add(ms);
} catch (Throwable t) {
throw new RuntimeException("Failed to get the length of the response.", t);
}
}
}
public void didAppendToResponse(WOElement element, WOResponse response, WOContext context) {
if (_markupEnabled) {
try {
CharSequence contentStr = (CharSequence) _contentField.get(response);
if (contentStr != null) {
List<MarkerStats> markerList = _markerList.get();
MarkerStats markerStats = markerList.remove(markerList.size() - 1);
int startIndex = markerStats._index;
int markerIndex = indexOf(contentStr, PFMarkup._marker, startIndex);
if (markerIndex != -1) {
replace(contentStr, markerIndex, markerIndex + PFMarkup._marker.length(), "");
startIndex = markerIndex;
int tagIndex = -1;
int endIndex = contentStr.length();
for (int i = startIndex; i < endIndex; i++) {
char ch = contentStr.charAt(i);
if (ch == '<') {
if (i < endIndex - 1 && contentStr.charAt(i + 1) != '/' && contentStr.charAt(i + 1) != '!') {
tagIndex = i;
break;
}
}
}
if (tagIndex != -1) {
String profilerIDAttributeName = "class";
String profilerIDAttributeStart = " " + profilerIDAttributeName + "=\"";
boolean foundClassAttribute = false;
int closeOffset = StringUtils.indexOf(contentStr, '>', tagIndex);
int attributeOffset = StringUtils.indexOf(contentStr, profilerIDAttributeName, tagIndex);
if (attributeOffset == -1 || attributeOffset > closeOffset) {
char ch = contentStr.charAt(closeOffset - 1);
if (ch == '/') {
attributeOffset = closeOffset - 1;
} else {
attributeOffset = closeOffset;
}
} else {
attributeOffset += profilerIDAttributeStart.length() -1;
foundClassAttribute = true;
}
String profilerID = markerStats._stats.cssID();
if (foundClassAttribute) {
insert(contentStr, attributeOffset, profilerID + " ");
} else {
insert(contentStr, attributeOffset, profilerIDAttributeStart + profilerID + "\"");
}
}
}
}
} catch (Throwable t) {
throw new RuntimeException("Failed to replace markers in the response.", t);
}
}
}
protected static class MarkerStats {
public PFStatsNode _stats;
public int _index;
}
}