/*
* Copyright (c) 2008-2019 Emmanuel Dupuy.
* This project is distributed under the GPLv3 license.
* This is a Copyleft license that gives the user the right to use,
* copy and modify the code freely for non-commercial purposes.
*/
package org.jd.gui.view.component;
import org.jd.gui.api.API;
import org.jd.gui.api.feature.IndexesChangeListener;
import org.jd.gui.api.feature.UriGettable;
import org.jd.gui.api.model.Container;
import org.jd.gui.api.model.Indexes;
import org.jd.gui.util.exception.ExceptionUtil;
import org.jd.gui.util.index.IndexesUtil;
import java.awt.*;
import java.net.URI;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
public class LogPage extends HyperlinkPage implements UriGettable, IndexesChangeListener {
protected API api;
protected URI uri;
protected Collection<Future<Indexes>> collectionOfFutureIndexes = Collections.emptyList();
public LogPage(API api, URI uri, String content) {
this.api = api;
this.uri = uri;
// Parse
int index = 0;
int eol = content.indexOf('\n');
while (eol != -1) {
parseLine(content, index, eol);
index = eol + 1;
eol = content.indexOf('\n', index);
}
parseLine(content, index, content.length());
// Display
setText(content);
}
protected void parseLine(String content, int index, int eol) {
int start = content.indexOf("at ", index);
if ((start != -1) && (start < eol)) {
int leftParenthesisIndex = content.indexOf('(', start);
if ((leftParenthesisIndex != -1) && (leftParenthesisIndex < eol)) {
addHyperlink(new LogHyperlinkData(start+3, leftParenthesisIndex));
}
}
}
protected boolean isHyperlinkEnabled(HyperlinkData hyperlinkData) { return ((LogHyperlinkData)hyperlinkData).enabled; }
protected void openHyperlink(int x, int y, HyperlinkData hyperlinkData) {
LogHyperlinkData logHyperlinkData = (LogHyperlinkData)hyperlinkData;
if (logHyperlinkData.enabled) {
try {
// Save current position in history
Point location = textArea.getLocationOnScreen();
int offset = textArea.viewToModel(new Point(x - location.x, y - location.y));
api.addURI(new URI(uri.getScheme(), uri.getAuthority(), uri.getPath(), "position=" + offset, null));
// Open link
String text = getText();
String typeAndMethodNames = text.substring(hyperlinkData.startPosition, hyperlinkData.endPosition);
int lastDotIndex = typeAndMethodNames.lastIndexOf('.');
String methodName = typeAndMethodNames.substring(lastDotIndex + 1);
String internalTypeName = typeAndMethodNames.substring(0, lastDotIndex).replace('.', '/');
List<Container.Entry> entries = IndexesUtil.findInternalTypeName(collectionOfFutureIndexes, internalTypeName);
int leftParenthesisIndex = hyperlinkData.endPosition + 1;
int rightParenthesisIndex = text.indexOf(')', leftParenthesisIndex);
String lineNumberOrNativeMethodFlag = text.substring(leftParenthesisIndex, rightParenthesisIndex);
if (lineNumberOrNativeMethodFlag.equals("Native Method")) {
// Example: at java.security.AccessController.doPrivileged(Native Method)
lastDotIndex = internalTypeName.lastIndexOf('/');
String shortTypeName = internalTypeName.substring(lastDotIndex + 1);
api.openURI(x, y, entries, null, shortTypeName + '-' + methodName + "-(*)?");
} else {
// Example: at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
int colonIndex = lineNumberOrNativeMethodFlag.indexOf(':');
String lineNumber = lineNumberOrNativeMethodFlag.substring(colonIndex + 1);
api.openURI(x, y, entries, "lineNumber=" + lineNumber, null);
}
} catch (Exception e) {
assert ExceptionUtil.printStackTrace(e);
}
}
}
// --- UriGettable --- //
public URI getUri() { return uri; }
// --- ContentSavable --- //
public String getFileName() {
String path = uri.getPath();
int index = path.lastIndexOf('/');
return path.substring(index + 1);
}
// --- IndexesChangeListener --- //
public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) {
// Update the list of containers
this.collectionOfFutureIndexes = collectionOfFutureIndexes;
// Refresh links
boolean refresh = false;
String text = getText();
for (Map.Entry<Integer, HyperlinkData> entry : hyperlinks.entrySet()) {
LogHyperlinkData entryData = (LogHyperlinkData)entry.getValue();
String typeAndMethodNames = text.substring(entryData.startPosition, entryData.endPosition);
int lastDotIndex = typeAndMethodNames.lastIndexOf('.');
String internalTypeName = typeAndMethodNames.substring(0, lastDotIndex).replace('.', '/');
boolean enabled = IndexesUtil.containsInternalTypeName(collectionOfFutureIndexes, internalTypeName);
if (entryData.enabled != enabled) {
entryData.enabled = enabled;
refresh = true;
}
}
if (refresh) {
textArea.repaint();
}
}
public static class LogHyperlinkData extends HyperlinkData {
public boolean enabled = false;
public LogHyperlinkData(int startPosition, int endPosition) {
super(startPosition, endPosition);
}
}
}