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-2007 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: package org.netbeans.modules.visualweb.errorhandler;
042:
043: import org.netbeans.api.project.Project;
044: import org.netbeans.api.project.ui.OpenProjects;
045: import java.awt.Toolkit;
046: import java.beans.PropertyChangeEvent;
047: import java.beans.PropertyChangeListener;
048: import java.io.BufferedReader;
049: import java.io.File;
050: import java.io.IOException;
051: import java.io.InputStreamReader;
052: import java.io.PrintWriter;
053: import java.net.ServerSocket;
054: import java.net.Socket;
055: import java.util.Date;
056: import javax.swing.JTextArea;
057: import javax.swing.SwingUtilities;
058: import org.openide.ErrorManager;
059: import org.openide.cookies.EditorCookie;
060: import org.openide.filesystems.FileObject;
061: import org.openide.loaders.DataObject;
062: import org.openide.loaders.DataObjectNotFoundException;
063: import org.openide.text.Annotatable;
064: import org.openide.text.Annotation;
065: import org.openide.text.Line;
066: import org.openide.windows.WindowManager;
067:
068: /*
069: * ClientSocketThread.java
070: * Created on January 6, 2004, 1:05 PM
071: */
072:
073: /**
074: * @author Winston Prakash
075: */
076: public class ClientSocketConnectionThread extends Thread {
077: BufferedReader in = null;
078: PrintWriter out = null;
079:
080: StringBuffer message = new StringBuffer();
081:
082: boolean connected = true;
083:
084: Socket clientSocket = null;
085: String threadName = null;
086:
087: DebugProtocol debugProtocol = new DebugProtocol();
088:
089: public ClientSocketConnectionThread(ThreadGroup threadGroup,
090: String threadName, Socket clientSocket) {
091: super (threadGroup, threadName);
092: this .threadName = threadName;
093: this .clientSocket = clientSocket;
094: }
095:
096: public void run() {
097: String line = null;
098: try {
099: in = new BufferedReader(new InputStreamReader(clientSocket
100: .getInputStream()));
101: out = new PrintWriter(clientSocket.getOutputStream(), true);
102: } catch (IOException exc) {
103: displayText("Could not get client socket I/O : "
104: + exc.getLocalizedMessage());
105: }
106:
107: while (connected) {
108: try {
109: line = in.readLine();
110: if (line != null) {
111: processText(line, true);
112: message.append(line + "\n");
113: } else {
114: //displayText("Client connection closed - " + threadName);
115: connected = false;
116: disconnect();
117: }
118: } catch (IOException exc) {
119: displayText(exc.getLocalizedMessage() + " - "
120: + threadName);
121: connected = false;
122: disconnect();
123: }
124: }
125: }
126:
127: public void disconnect() {
128: if (connected) {
129: try {
130: out.close();
131: in.close();
132: clientSocket.close();
133: } catch (IOException exc) {
134: //displayText("Error occured while disconnecting socket" + exc.getLocalizedMessage());
135: }
136: out = null;
137: in = null;
138: clientSocket = null;
139: connected = false;
140: }
141: }
142:
143: public void sendMessage(String text) {
144: if (out != null) {
145: out.println(text);
146: }
147: }
148:
149: public String getMessage() {
150: return message.toString();
151: }
152:
153: private void displayText(String line) {
154: processText(line, false);
155: }
156:
157: private void processText(String line, boolean process) {
158: // Procees the Text
159:
160: if (process) {
161: final String processedOutput = debugProtocol
162: .processInput(line);
163:
164: //DebugServerTestWindow.displayMessage(processedOutput);
165: //System.out.println(processedOutput);
166:
167: // Disconnect if the client is not recognized
168: if (debugProtocol.getState() == DebugProtocol.STATE_CLIENT_UNRCOGNIZED) {
169: //System.out.println(" disconnecting ..\n");
170: disconnect();
171: debugProtocol.setState(DebugProtocol.STATE_WAITING);
172: }
173:
174: if (debugProtocol.getState() == DebugProtocol.STATE_DONE) {
175: disconnect();
176: showErrorLine(debugProtocol.getErrorInfo());
177: debugProtocol.setState(DebugProtocol.STATE_WAITING);
178: //DebugServerTestWindow.displayMessage("\n");
179: //System.out.println("\n");
180: }
181:
182: } else {
183: //DebugServerTestWindow.displayMessage(line);
184: //System.out.println(line);
185: }
186: }
187:
188: private void showErrorLine(DebugProtocol.ErrorInfo errorInfo) {
189: String filePath = errorInfo.getFilePath();
190: /*** filePath is something like "WebApplication1/Page2.java" (package/Page).
191: * also can get faces stuff, like com/sun/faces/el/MethodBindingImpl.java
192: */
193: int lineNumber = errorInfo.getLineNumber();
194:
195: Project[] openProjects = OpenProjects.getDefault()
196: .getOpenProjects();
197: Project currentProject = null;
198: String resourcePath = "src/" + filePath;
199: FileObject srcFile = null;
200:
201: for (int i = 0; srcFile == null && openProjects != null
202: && i < openProjects.length; i++) {
203: Project nextProject = openProjects[i];
204: try {
205: FileObject errorFile = nextProject
206: .getProjectDirectory().getFileObject(
207: resourcePath);
208: if (errorFile != null) {
209: srcFile = errorFile;
210: currentProject = nextProject;
211: }
212: } catch (Exception ex) {
213: }
214: }
215:
216: if (currentProject == null) {
217: return;
218: }
219:
220: try {
221: DataObject dob = DataObject.find(srcFile);
222: new ErrorLineMarker().markError(dob, lineNumber);
223: } catch (DataObjectNotFoundException ex) {
224: ErrorManager.getDefault().notify(ErrorManager.WARNING, ex);
225: }
226:
227: }
228:
229: private static final class ErrorLineMarker extends Annotation
230: implements PropertyChangeListener {
231:
232: public void markError(DataObject dob, int lineNo) {
233: try {
234: EditorCookie ed = (EditorCookie) dob
235: .getCookie(EditorCookie.class);
236: if (ed != null) {
237: //displayText("Got the editor cookie.");
238: if (lineNo == -1) {
239: // OK, just open it.
240: ed.open();
241: } else {
242: ed.openDocument(); // XXX getLineSet does not do it for you
243: final Line line = ed.getLineSet().getOriginal(
244: lineNo - 1);
245: if (!line.isDeleted()) {
246: SwingUtilities.invokeLater(new Runnable() {
247: public void run() {
248: attachAsNeeded(line);
249: line.show(Line.SHOW_GOTO);
250: WindowManager.getDefault()
251: .getMainWindow().toFront();
252: }
253: });
254: }
255: }
256: } else {
257: Toolkit.getDefaultToolkit().beep();
258: }
259: } catch (DataObjectNotFoundException donfe) {
260: ErrorManager.getDefault().notify(ErrorManager.WARNING,
261: donfe);
262: } catch (IndexOutOfBoundsException iobe) {
263: ErrorManager.getDefault().notify(ErrorManager.WARNING,
264: iobe);
265: } catch (IOException ioe) {
266: // XXX see above, should not be necessary to call openDocument at all
267: ErrorManager.getDefault().notify(ErrorManager.WARNING,
268: ioe);
269: }
270: }
271:
272: private synchronized void attachAsNeeded(Line line) {
273: if (getAttachedAnnotatable() == null) {
274: // Attach the whole line
275: Annotatable ann = line;
276: // System.out.println("Attaching to line " + line.getDisplayName() + " text=`" + line.getText() );
277: attach(ann);
278: ann.addPropertyChangeListener(this );
279: }
280: }
281:
282: private synchronized void doDetach() {
283: Annotatable ann = getAttachedAnnotatable();
284: if (ann != null) {
285: ann.removePropertyChangeListener(this );
286: detach();
287: }
288: }
289:
290: public void propertyChange(PropertyChangeEvent ev) {
291: String prop = ev.getPropertyName();
292: if (prop == null || prop.equals(Annotatable.PROP_TEXT)
293: || prop.equals(Annotatable.PROP_DELETED)) {
294: // Affected line has changed.
295: // Assume user has edited & corrected the error.
296: doDetach();
297: }
298: }
299:
300: // Annotation:
301: public String getAnnotationType() {
302: return "com-sun-rave-errorhandler-error"; // NOI18N
303: }
304:
305: public String getShortDescription() {
306: return "Error Handler Marker"; // NOI18N
307: }
308: }
309: }
|