001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.web.jspcompiler;
043:
044: import java.io.File;
045: import java.util.logging.Level;
046: import java.util.logging.Logger;
047: import java.util.regex.Matcher;
048: import java.util.regex.Pattern;
049: import org.apache.tools.ant.module.spi.AntEvent;
050: import org.apache.tools.ant.module.spi.AntLogger;
051: import org.apache.tools.ant.module.spi.AntSession;
052: import org.netbeans.modules.web.api.webmodule.WebModule;
053: import org.openide.filesystems.FileObject;
054: import org.openide.filesystems.FileStateInvalidException;
055: import org.openide.filesystems.FileUtil;
056:
057: /**
058: * Ant logger which handles compilation of JSPs
059: * @author Martin Grebac
060: */
061: public final class TldAntLogger extends AntLogger {
062:
063: /**
064: * Regexp matching the compilation error from JspC when error is in tld. Sample message could look like this:
065: * org.apache.jasper.JasperException: Unable to initialize TldLocationsCache: XML parsing error on file /WEB-INF/jsp2/jsp2-example-taglib.tld: (line 18, col -1)
066: */
067: private static final Pattern TLD_ERROR = Pattern
068: .compile("(.*)(org.apache.jasper.JasperException:)(.*)( file )(.*)"); // NOI18N
069:
070: private static final Pattern FILE_PATTERN = Pattern
071: .compile("([^\\(]*)(: )\\(line ([0-9]+), col ([0-9-]+)\\)"); // NOI18N
072:
073: private static final String[] TASKS_OF_INTEREST = AntLogger.ALL_TASKS;
074:
075: private static final int[] LEVELS_OF_INTEREST = {
076: //AntEvent.LOG_DEBUG, // XXX is this needed?
077: //AntEvent.LOG_VERBOSE, // XXX is this needed?
078: AntEvent.LOG_INFO, // XXX is this needed?
079: AntEvent.LOG_WARN, // XXX is this needed?
080: AntEvent.LOG_ERR, // XXX is this needed?
081: };
082:
083: private static final Logger ERR = Logger
084: .getLogger(TldAntLogger.class.getName());
085: private static final boolean LOGGABLE = ERR.isLoggable(Level.FINE);
086:
087: /** Default constructor for lookup. */
088: public TldAntLogger() {
089: }
090:
091: public boolean interestedInSession(AntSession session) {
092: return true;
093: }
094:
095: public boolean interestedInAllScripts(AntSession session) {
096: return true;
097: }
098:
099: public String[] interestedInTargets(AntSession session) {
100: return AntLogger.ALL_TARGETS;
101: }
102:
103: public boolean interestedInScript(File script, AntSession session) {
104: return true;
105: }
106:
107: public String[] interestedInTasks(AntSession session) {
108: return TASKS_OF_INTEREST;
109: }
110:
111: public int[] interestedInLogLevels(AntSession session) {
112: // XXX could exclude those in [INFO..ERR] greater than session.verbosity
113: return LEVELS_OF_INTEREST;
114: }
115:
116: public void messageLogged(AntEvent event) {
117: AntSession session = event.getSession();
118: int messageLevel = event.getLogLevel();
119: int sessionLevel = session.getVerbosity();
120: String line = event.getMessage();
121: assert line != null;
122:
123: Matcher m = TLD_ERROR.matcher(line);
124: if (m.matches()) { //it's our error
125: if (LOGGABLE)
126: ERR.log(Level.FINE, "matched line: " + line);
127: // print the exception and error statement first
128: String errorText = m.group(3) + m.group(4);
129: session.println(m.group(2) + errorText, true, null);
130:
131: // get the file from the line
132: String filePart = m.group(5).trim();
133: if (LOGGABLE)
134: ERR.log(Level.FINE, "file part: " + filePart);
135:
136: // now create hyperlink for the file
137: Matcher fileMatcher = FILE_PATTERN.matcher(filePart);
138: if (fileMatcher.matches()) {
139: String tldFile = fileMatcher.group(1).trim();
140: if (LOGGABLE)
141: ERR.log(Level.FINE, "tld file: " + tldFile);
142:
143: int lineNumber = Integer.parseInt(fileMatcher.group(3));
144: int columnNumber = Integer.parseInt(fileMatcher
145: .group(4));
146: if (LOGGABLE)
147: ERR.log(Level.FINE, "linking line: " + lineNumber
148: + ", column: " + columnNumber);
149:
150: File scriptLoc = event.getScriptLocation();
151: FileObject scriptLocFO = FileUtil
152: .toFileObject(scriptLoc);
153: WebModule wm = WebModule.getWebModule(scriptLocFO);
154: if (LOGGABLE)
155: ERR.log(Level.FINE, "wm: " + wm);
156:
157: if (wm == null) {
158: session.println(tldFile, true, null);
159: event.consume();
160: return;
161: }
162:
163: FileObject tldSource = wm.getDocumentBase()
164: .getFileObject(tldFile);
165: if (LOGGABLE)
166: ERR.log(Level.FINE, "tldSource: " + tldSource);
167:
168: if (tldSource == null) {
169: session.println(tldFile, true, null);
170: event.consume();
171: return;
172: }
173:
174: if (messageLevel <= sessionLevel && !event.isConsumed()) {
175: try {
176: session.println(tldFile, true, session
177: .createStandardHyperlink(tldSource
178: .getURL(), errorText + tldFile,
179: lineNumber, columnNumber, -1,
180: -1));
181: } catch (FileStateInvalidException e) {
182: assert false : e;
183: }
184: }
185: }
186: event.consume();
187: }
188: }
189: }
|