/******************************************************************************* * Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Exadel, Inc. and Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.common.model.util; import java.util.*; import org.jboss.tools.common.meta.action.*; import org.jboss.tools.common.model.*; public class FindObjectHelper implements SpecialWizard { public static int EVERY_WHERE = 0; public static int IN_EDITOR_ONLY = 1; public static int IN_NAVIGATOR_ONLY = 2; public static int IN_NAVIGATOR_AND_IN_EDITOR_IF_OPEN = 3; static SpecialWizard select = createSelectWizard(); private XModel model = null; private String command = null; private int off = -1; private FileInfo file = new FileInfo(); private SegmentInfo segment = new SegmentInfo(); private int line = -1; public static SpecialWizard createSelectWizard() { return SpecialWizardFactory.createSpecialWizard("org.jboss.tools.common.model.ui.select.SelectObjectWizard"); //$NON-NLS-1$ } public static int findModelObject(XModelObject o, int where) { if(o == null) return 1; SpecialWizard wizard = createSelectWizard(); wizard.setObject(Integer.valueOf(where)); wizard.setObject(o); return wizard.execute(); } public static int findModelObject(XModelObject o, int where, String preferredPage) { if(o == null) return 1; SpecialWizard wizard = createSelectWizard(); wizard.setObject(Integer.valueOf(where)); wizard.setObject(o); wizard.setObject(preferredPage); return wizard.execute(); } public static String makeRef(XModelObject o) { return "" + o.getAttributeValue(XModelObjectConstants.ATTR_ELEMENT_TYPE) + " " + makeRef(o.getPath(), o.getPresentationString()); //$NON-NLS-1$ //$NON-NLS-2$ } public static String makeRef(XModelObject o, int line) { return "" + o.getAttributeValue(XModelObjectConstants.ATTR_ELEMENT_TYPE) + " " + makeRef(o.getPath() + ":" + line, o.getPresentationString()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } public static String makeRef(String hidden, String visible) { return "@" + hidden + "@" + visible + "@"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } public FindObjectHelper() {} public void setObject(Object object) { Object[] os = (Object[])object; model = (XModel)os[0]; command = (String)os[1]; off = ((Integer)os[2]).intValue(); } public int execute() { XModelObject o = findRef(); if(o == null) o = findJava(); if(o != null) { o.set("_error_line_", "" + line); //$NON-NLS-1$ //$NON-NLS-2$ select.setObject(o); select.execute(); o.set("_error_line_", ""); //$NON-NLS-1$ //$NON-NLS-2$ } return 0; } private XModelObject findRef() { int i = 0; while(i < command.length()) { int i1 = command.indexOf("@", i); //$NON-NLS-1$ if(i1 < 0 || i1 > off) return null; int i2 = command.indexOf("@", i1 + 1); //$NON-NLS-1$ if(i2 < 0) return null; String p = command.substring(i1 + 1, i2); int i3 = command.indexOf("@", i2 + 1); //$NON-NLS-1$ if(i3 < 0) return null; if(i3 >= off) { int q = p.indexOf(":"); //$NON-NLS-1$ if(q >= 0) { try { line = Integer.parseInt(p.substring(q + 1)); } catch (NumberFormatException e) { //ignore } p = p.substring(0, q); } return model.getByPath(p); } i = i3 + 1; } return null; } private XModelObject findJava() { JavacErrorHeadLine h = new JavacErrorHeadLine(model, command); if(h.jf() != null) file.setData(h.jf(), h.line(), model); else if(h.cls() != null) file.setData(h.cls(), h.line(), model); else return null; XModelObject o = model.getByPath(file.getJPath()); line = file.getLine() - 1; if (o != null) return o; if(file.getText().length() == 0) return null; segment.setData(file); segment.parse(); String path = segment.getPath(); if(path == null) return null; o = model.getByPath(path); line = segment.getLine(); return o; } public static String enhanceStackTraceEntry(XModel model, String st) { StackTraceLine q = new StackTraceLine(st); if(q.cls() == null) return st; FileInfo f = new FileInfo(); f.setData(q.cls(), q.line() + 1, model); XModelObject o = model.getByPath(f.getJPath()); if(o != null) { return q.getLineStart() + makeRef(o.getPath() + ":" + q.line(), q.toString()); //$NON-NLS-1$ } else if(q.line() < 0) { return st; } SegmentInfo s = new SegmentInfo(); s.setData(f); s.parse(); String path = s.getPath(); o = (path == null) ? null : model.getByPath(path); if(o == null) return st; return q.getLineStart() + makeRef(o.getPath() + ":" + s.getLine(), q.toString()); //$NON-NLS-1$ } } class FileInfo { private String text = ""; //$NON-NLS-1$ private int line; private String jpath = ""; //$NON-NLS-1$ public void setData(String cls, int ln, XModel model) { jpath = XModelObjectConstants.SEPARATOR + cls.replace('.', '/') + ".java"; //$NON-NLS-1$ line = ln; String fn = "" + XModelObjectUtil.getExpandedValue(model.getByPath("Engines/generator"), "directory", null) + "/src" + jpath; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ text = XModelObjectLoaderUtil.readFile(fn); } public void setData(XModelObject cls, int ln, XModel model) { jpath = cls.getPath(); line = ln; text = cls.getAttributeValue(XModelObjectConstants.ATTR_NAME_BODY); } public String getJPath() { return jpath; } public String getText() { return text; } public int getLine() { return line; } } class SegmentInfo { private FileInfo file; private String path = null; private String attr = null; int line = -1; public SegmentInfo() {} public void setData(FileInfo file) { this.file = file; } public void parse() { path = null; String text = file.getText(); line = file.getLine(); int off = getOffset(text, line); int b = 0, e = 0; while(true) { b = text.indexOf("//<!--", e); //$NON-NLS-1$ if(b < 0) return; e = text.indexOf("//--", b); //$NON-NLS-1$ if(e < 0) return; if(e > off) break; } b = text.indexOf("//", b + 2); //$NON-NLS-1$ if(b < 0) return; int b2 = text.indexOf("\n", b); //$NON-NLS-1$ if(b2 < 0) return; path = text.substring(b + 2, b2); int q = path.lastIndexOf('.'); attr = path.substring(q + 1); if(q >= 0) path = path.substring(0, q); reduceLine(text, b2 + 1); } private int getOffset(String text, int ln) { StringTokenizer st = new StringTokenizer(text, "\n", true); //$NON-NLS-1$ int r = 0; while(ln > 1 && st.hasMoreTokens()) { String s = st.nextToken(); if("\n".equals(s)) --ln; //$NON-NLS-1$ r += s.length(); } return r; } private void reduceLine(String text, int b) { StringTokenizer st = new StringTokenizer(text, "\n", true); //$NON-NLS-1$ int r = 0; while(r < b && st.hasMoreTokens()) { String s = st.nextToken(); if("\n".equals(s)) --line; //$NON-NLS-1$ r += s.length(); } --line; } public String getPath() { return path; } public String getAttr() { return attr; } public int getLine() { return line; } } class StackTraceLine { public static String PREFIX = "\tat "; //$NON-NLS-1$ private String beg = null; private String cls = null; private String mtd = null; private int ln = -1; public StackTraceLine(String text) { int i = text.indexOf(PREFIX); if(i < 0) return; beg = text.substring(0, i); text = text.substring(i + PREFIX.length()).trim(); int ob = text.indexOf('('); if(ob < 0) return; int cb = text.indexOf(')', ob); if(cb < 0) return; int ld = text.lastIndexOf('.', ob); if(ld < 0) return; cls = text.substring(0, ld); mtd = text.substring(ld + 1, ob); int sc = text.indexOf(':', ob); if(sc < 0) sc = ob; String sln = text.substring(sc + 1, cb); try { ln = Integer.parseInt(sln) - 1; } catch (NumberFormatException e) { //ignore } } public String toString() { return cls + "." + mtd + "(" + (ln + 1) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } public String getLineStart() { return beg + PREFIX; } public String cls() { return cls; } public int line() { return ln; } public void setLine(int line) { ln = line; } } class JavacErrorHeadLine { private String cls = null; private int ln = -1; private XModelObject jf = null; public JavacErrorHeadLine(XModel model, String command) { int i = command.indexOf(".java:"); //$NON-NLS-1$ if(i < 0) return; int j = command.indexOf(':', i + 6); try { ln = Integer.parseInt(command.substring(i + 6, j)); } catch (NumberFormatException e) { //ignore } String fn = command.substring(0, i); fn = fn.substring(fn.indexOf(']') + 1).trim(); // Cut off ant task prefix. XModelObject g = model.getByPath("Engines/generator"); //$NON-NLS-1$ if(g != null) { String p = "" + XModelObjectUtil.getExpandedValue(g, "directory", null) + "/src/"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ cls = fn.substring(p.length()).replace('/', '.').replace('\\', '.'); } findJFile(model, XModelObjectConstants.SEPARATOR + fn.replace('\\', '/') + ".java"); //$NON-NLS-1$ } private void findJFile(XModel model, String fn) { jf = model.getByPath(fn); if(isOverlapped(jf)) jf = null; if(jf != null) return; int i = fn.indexOf('/', 1); if(i >= 0) findJFile(model, fn.substring(i)); } private boolean isOverlapped(XModelObject o) { while(o != null) { if(XModelObjectConstants.TRUE.equals(o.get("overlapped"))) return true; //$NON-NLS-1$ o = o.getParent(); } return false; } public String cls() { return cls; } public XModelObject jf() { return jf; } public int line() { return ln; } }