package act.util; /*- * #%L * ACT Framework * %% * Copyright (C) 2014 - 2017 ActFramework * %% * 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. * #L% */ import act.Act; import act.app.*; import act.asm.AsmContext; import org.osgl.util.C; import org.osgl.util.E; import org.osgl.util.S; import java.lang.annotation.ElementType; import java.lang.reflect.Method; import java.util.List; public interface ActError { Throwable getCauseOrThis(); Throwable getCause(); SourceInfo sourceInfo(); List<String> stackTrace(); String getMessage(); String getLocalizedMessage(); boolean isErrorSpot(String traceLine, String nextTraceLine); class Util { public static List<String> stackTraceOf(Throwable t, ActError root) { List<String> l = C.newList(); while (null != t) { StackTraceElement[] a = t.getStackTrace(); for (StackTraceElement e : a) { l.add("at " + e.toString()); } t = t.getCause(); if (t == root) { break; } if (null != t) { l.add("Caused by " + t.toString()); } } return l; } public static SourceInfo loadSourceInfo(StackTraceElement[] stackTraceElements, Class<? extends ActError> errClz) { E.illegalStateIf(Act.isProd()); DevModeClassLoader cl = (DevModeClassLoader) App.instance().classLoader(); for (StackTraceElement stackTraceElement : stackTraceElements) { int line = stackTraceElement.getLineNumber(); if (line <= 0) { continue; } String className = stackTraceElement.getClassName(); if (S.eq(errClz.getName(), className)) { continue; } Source source = cl.source(className); if (null == source) { continue; } return new SourceInfoImpl(source, line); } return null; } public static SourceInfo loadSourceInfo(Method method) { return loadSourceInfo(method.getDeclaringClass().getName(), method.getName(), true, null); } public static SourceInfo loadSourceInfo(AsmContext asmContext) { return loadSourceInfo(asmContext.className(), asmContext.name(), ElementType.METHOD == asmContext.type(), asmContext.lineNo()); } private static SourceInfo loadSourceInfo(String className, String elementName, boolean isMethod, Integer lineNo) { E.illegalStateIf(Act.isProd()); DevModeClassLoader cl = (DevModeClassLoader) App.instance().classLoader(); Source source = cl.source(className); if (null == source) { return null; } List<String> lines = source.lines(); Line candidate = null; String pattern = isMethod ? S.concat("^\\s*.*", elementName, "\\s*\\(.*") : S.concat("^\\s*.*", elementName, "[^\\(\\{]*"); if (null != lineNo) { return new SourceInfoImpl(source, lineNo); } for (int i = 0; i < lines.size(); ++i) { String line = lines.get(i); if (line.matches(pattern)) { candidate = new Line(line, i + 1); if (candidate.forSure) { return new SourceInfoImpl(source, candidate.no); } } } if (null != candidate) { return new SourceInfoImpl(source, candidate.no); } return new SourceInfoImpl(source, 1); } private static class Line { String line; int no; boolean forSure; Line(String line, int no) { this.line = line; this.no = no; forSure = line.contains("public "); } } } }