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:
042: /*
043: * REParser.java
044: *
045: * Created on March 2, 2005, 7:38 AM
046: */
047:
048: package org.netbeans.modules.uml.parser.java;
049:
050: import org.netbeans.modules.uml.parser.java.JavaLexer;
051: import org.netbeans.modules.uml.parser.java.JavaRecognizer;
052: import org.netbeans.modules.uml.parser.java.JavaTokenTypes;
053: import org.netbeans.modules.uml.parser.java.JavaTreeParser;
054: import org.netbeans.modules.uml.core.reverseengineering.parsers.javaparser.IREJavaParser;
055: import java.io.BufferedReader;
056: import java.io.FileNotFoundException;
057: import java.io.FileInputStream;
058: import java.io.InputStreamReader;
059: import java.io.IOException;
060: import java.io.PrintStream;
061: import java.io.StringReader;
062: import java.io.UnsupportedEncodingException;
063: import java.nio.charset.Charset;
064:
065: import org.dom4j.Node;
066:
067: import antlr.ANTLRException;
068: import antlr.CharBuffer;
069: import antlr.CommonASTWithLocationsAndHidden;
070: import antlr.CommonHiddenStreamToken;
071: import antlr.RecognitionException;
072: import antlr.TokenStreamHiddenTokenFilter;
073:
074: import org.netbeans.modules.uml.core.reverseengineering.reframework.IParserData;
075: import org.netbeans.modules.uml.core.reverseengineering.reframework.IREOperation;
076: import org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.CommentGather;
077: import org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.IErrorListener;
078: import org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.IStateFilter;
079: import org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.IStateListener;
080: import org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.ITokenDescriptor;
081: import org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.ITokenFilter;
082: import org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.ITokenProcessor;
083: import org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.ParserEventController;
084: import org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.ProcessTypeKind;
085:
086: /**
087: *
088: * @author Administrator
089: */
090: public class REJavaParser implements IREJavaParser {
091:
092: /** Creates a new instance of REParser */
093: public REJavaParser() {
094: }
095:
096: private ParserEventController m_EventController = new ParserEventController(
097: new CommentGather(JavaTokenTypes.SL_COMMENT,
098: JavaTokenTypes.ML_COMMENT), "Java");
099:
100: private String m_Filename;
101:
102: /* (non-Javadoc)
103: * @see org.netbeans.modules.uml.core.reverseengineering.parsers.javaparser.IREJavaParser#notifyPackageEvent(org.dom4j.Node)
104: */
105: public void notifyPackageEvent(Node eventData) {
106: // Missing in C++ code.
107: }
108:
109: /* (non-Javadoc)
110: * @see org.netbeans.modules.uml.core.reverseengineering.parsers.javaparser.IREJavaParser#notifyDependencyEvent(org.dom4j.Node)
111: */
112: public void notifyDependencyEvent(Node eventData) {
113: // Missing in C++ code.
114: }
115:
116: /* (non-Javadoc)
117: * @see org.netbeans.modules.uml.core.reverseengineering.parsers.javaparser.IREJavaParser#notifyClassEvent(org.dom4j.Node)
118: */
119: public void notifyClassEvent(Node eventData) {
120: // Missing in C++ code.
121: }
122:
123: /* (non-Javadoc)
124: * @see org.netbeans.modules.uml.core.reverseengineering.parsers.javaparser.IREJavaParser#notifyActionEvent(org.dom4j.Node)
125: */
126: public void notifyActionEvent(Node eventData) {
127: // Missing in C++ code.
128: }
129:
130: /* (non-Javadoc)
131: * @see org.netbeans.modules.uml.core.reverseengineering.parsers.javaparser.IREJavaParser#notifyError(antlr.RecognitionException)
132: */
133: public void notifyError(RecognitionException e) {
134: // Missing in C++ code.
135: }
136:
137: /* (non-Javadoc)
138: * @see org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.ILanguageParser#parseFile(java.lang.String, java.lang.String)
139: */
140: public void parseFile(String filename, String charset) {
141: try {
142: InputStreamReader reader = null;
143: if (charset != null) {
144: try {
145: reader = new InputStreamReader(new FileInputStream(
146: filename), charset);
147: } catch (UnsupportedEncodingException uee) {
148: // catch it here thus giving chance
149: // to default charset version below
150: }
151: }
152: if (reader == null) {
153: reader = new InputStreamReader(new FileInputStream(
154: filename));
155: }
156: BufferedReader bufr = new BufferedReader(reader);
157: CharBuffer buffer = new CharBuffer(bufr);
158: processStreamAsFile(buffer, filename);
159: bufr.close();
160: reader.close();
161: } catch (FileNotFoundException e) {
162: e.printStackTrace();
163: } catch (IOException e) {
164: e.printStackTrace();
165: }
166: }
167:
168: /* (non-Javadoc)
169: * @see org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.ILanguageParser#parseFile(java.lang.String)
170: */
171: public void parseFile(String filename) {
172: parseFile(filename, null);
173: }
174:
175: /* (non-Javadoc)
176: * @see org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.ILanguageParser#parseOperation(java.lang.String, java.lang.String, org.netbeans.modules.uml.core.reverseengineering.reframework.IREOperation)
177: */
178: public void parseOperation(String filename, String charset,
179: IREOperation operation) {
180: if (filename != null && operation != null) {
181: // Now that I have the parser I can create a OperationBuffer and
182: // give it to the parser to start parsing.
183: long start = getPosition(operation, "StartPosition"), end = getPosition(
184: operation, "EndPosition");
185: // This is non-ideal, but easier than creating a constrained Reader
186: // TODO: Fix this to use a constrained Reader so that we
187: // don't introduce a memory bottleneck here.
188: String text = extractText(filename, charset, (int) start,
189: (int) end);
190: StringReader read = new StringReader(text);
191: CharBuffer buf = new CharBuffer(read);
192: processStreamAsFragment(buf, filename);
193: }
194: }
195:
196: /* (non-Javadoc)
197: * @see org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.ILanguageParser#parseOperation(java.lang.String, org.netbeans.modules.uml.core.reverseengineering.reframework.IREOperation)
198: */
199: public void parseOperation(String filename, IREOperation operation) {
200: parseOperation(filename, null, operation);
201: }
202:
203: private long getPosition(IParserData data, String tagname) {
204: long pos = -1;
205:
206: ITokenDescriptor desc = data.getTokenDescriptor(tagname);
207: if (desc != null && tagname.equals(desc.getType())) {
208: pos = desc.getPosition();
209: if ("EndPosition".equals(tagname))
210: pos += desc.getLength();
211: }
212: return pos;
213: }
214:
215: private String extractText(String filename, String charset,
216: int start, int end) {
217: if (end < start)
218: return null;
219:
220: try {
221: InputStreamReader reader = null;
222: if (charset != null) {
223: try {
224: reader = new InputStreamReader(new FileInputStream(
225: filename), charset);
226: } catch (UnsupportedEncodingException uee) {
227: // catch it here thus giving chance
228: // to default charset version below
229: }
230: }
231: if (reader == null) {
232: reader = new InputStreamReader(new FileInputStream(
233: filename));
234: }
235: BufferedReader bufr = new BufferedReader(reader);
236: bufr.skip(start);
237:
238: char[] readc = new char[end - start];
239: int readchars = bufr.read(readc);
240: bufr.close();
241: reader.close();
242: return new String(readc, 0, readchars);
243: } catch (Exception e) {
244: e.printStackTrace();
245: }
246: return null;
247: }
248:
249: /**
250: * Gets the state listener for the parser. The state listener will recieve
251: * state events as the parser changes state. When the state filter filters
252: * out a state a state events will not be sent to the state listener.
253: *
254: * @param pVal [out] The state listener.
255: * @see #get_StateFilter(IStateFilter* *pVal)
256: */
257: public IStateListener getStateListener() {
258: return m_EventController.getStateListener();
259: }
260:
261: /**
262: * Sets the state listener for the parser. The state listener will recieve
263: * state events as the parser changes state. When the state filter filters
264: * out a state a state events will not be sent to the state listener.
265: *
266: * @param newVal [in] The state listener.
267: * @see #put_StateFilter(IStateFilter* newVal)
268: */
269: public void setStateListener(IStateListener stateListener) {
270: m_EventController.setStateListener(stateListener);
271: }
272:
273: /**
274: * Gets the state filter for the parser. The state filter determines
275: * if a state is to be filtered or not. When a state is filtered all sub
276: * states are also filtered. The token listener will not recieve any
277: * token events found while in a filtered state.
278: *
279: * @param pVal [out] The state filter.
280: * @see #get_StateListener(IStateListener* *pVal)
281: */
282: public IStateFilter getStateFilter() {
283: return m_EventController.getStateFilter();
284: }
285:
286: /**
287: * Sets the state filter for the parser. The state filter determines
288: * if a state is to be filtered or not. When a state is filtered all sub
289: * states are also filtered. The token listener will not recieve any
290: * token events found while in a filtered state.
291: *
292: * @param newVal [in] The state filter.
293: * @see #put_StateListener (IStateListener* newVal)
294: */
295: public void setStateFilter(IStateFilter filter) {
296: m_EventController.setStateFilter(filter);
297: }
298:
299: /**
300: * Get the the interface that will process tokens found while
301: * parsing a file. Tokens will not be sent while in a state
302: * that has bee filtered out,
303: *
304: * @param pVal [out] The token processor.
305: */
306: public ITokenProcessor getTokenProcessor() {
307: return m_EventController.getTokenProcessor();
308: }
309:
310: /**
311: * Set the the interface that will process tokens found while
312: * parsing a file. Tokens will not be sent while in a state
313: * that has bee filtered out,
314: *
315: * @param newVal [in] The token processor.
316: */
317: public void setTokenProcessor(ITokenProcessor tokenProcessor) {
318: m_EventController.setTokenProcessor(tokenProcessor);
319: }
320:
321: /**
322: * Get the the interface that will be used to filter tokens
323: * before they are sent to the token processor. Tokens will
324: * not be sent if they have be filtered out.
325: *
326: * @param pVal [out] The token filter.
327: */
328: public ITokenFilter getTokenFilter() {
329: return m_EventController.getTokenFilter();
330: }
331:
332: /**
333: * Set the the interface that will be used to filter tokens
334: * before they are sent to the token processor. Tokens will
335: * not be sent if they have be filtered out.
336: *
337: * @param pVal [out] The token filter.
338: */
339: public void setTokenFilter(ITokenFilter filter) {
340: m_EventController.setTokenFilter(filter);
341: }
342:
343: /**
344: * Get the the interface that will recieve the error information
345: * will parsing the file.
346: *
347: * @param pVal [out] The error listener.
348: */
349: public IErrorListener getErrorListener() {
350: return m_EventController.getErrorListener();
351: }
352:
353: /**
354: * Set the the interface that will recieve the error information
355: * will parsing the file.
356: *
357: * @param newVal [int] The error listener.
358: */
359: public void setErrorListener(IErrorListener errorListener) {
360: m_EventController.setErrorListener(errorListener);
361: }
362:
363: /* (non-Javadoc)
364: * @see org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.ILanguageParser#processStreamByType(java.lang.String, int)
365: */
366: public void processStreamByType(String stream, int type) {
367: StringReader sr = new StringReader(stream);
368: CharBuffer cb = new CharBuffer(sr);
369: if (type == ProcessTypeKind.PTK_PROCESS_FILE)
370: processStreamAsFile(cb, null);
371: else if (type == ProcessTypeKind.PTK_PROCESS_FRAGMENT)
372: processStreamAsFragment(cb, null);
373: }
374:
375: private void processStreamAsFragment(CharBuffer buffer,
376: String filename) {
377: // Create a scanner that reads from the input stream
378: JavaLexer lexer = new JavaLexer(buffer);
379: if (filename != null)
380: lexer.setFilename(filename);
381: lexer.setTokenObjectClass(CommonHiddenStreamToken.class
382: .getName());
383: // lexer.setTokenObjectFactory(&antlr::CommonHiddenStreamToken::factory);
384:
385: lexer.setEventController(m_EventController);
386:
387: // Now initialize create and initialize a filter to keep track of
388: // WS and Comments.
389: TokenStreamHiddenTokenFilter filter = new TokenStreamHiddenTokenFilter(
390: lexer);
391: filter.hide(JavaLexer.SL_COMMENT);
392: filter.hide(JavaLexer.ML_COMMENT);
393:
394: // Create a parser that reads from the scanner
395: JavaRecognizer parser = new JavaRecognizer(filter);
396: parser.setASTNodeClass(CommonASTWithLocationsAndHidden.class
397: .getName());
398:
399: // parser.setASTNodeFactory(&antlr::CommonASTWithLocationsAndHidden::factory);
400:
401: try {
402: parser.setEventController(m_EventController);
403: parser.methodCompilationUnit();
404: } catch (ANTLRException e) {
405: m_EventController.errorFound(e.getMessage(), -1, -1,
406: filename);
407: }
408:
409: try {
410: JavaTreeParser treeParser = new JavaTreeParser();
411: treeParser.setEventController(m_EventController);
412: treeParser.parseMethodBody(parser.getAST());
413: } catch (ANTLRException e) {
414: m_EventController.errorFound(e.getMessage(), -1, -1,
415: filename);
416: }
417: }
418:
419: private void processStreamAsFile(CharBuffer buffer, String filename) {
420: if (filename != null)
421: m_EventController.setFilename(filename);
422: try {
423: // Create a scanner that reads from the input stream
424: JavaLexer lexer = new JavaLexer(buffer);
425: //JavaLexer lexer(s);
426: if (filename != null)
427: lexer.setFilename(filename);
428:
429: lexer.setTokenObjectClass(CommonHiddenStreamToken.class
430: .getName());
431: // lexer.setTokenObjectFactory(CommonHiddenStreamToken.class);
432: lexer.setEventController(m_EventController);
433:
434: // Now initialize create and initialize a filter to keep track of
435: // WS and Comments.
436: TokenStreamHiddenTokenFilter filter = new TokenStreamHiddenTokenFilter(
437: lexer);
438: filter.hide(JavaLexer.WS);
439: filter.hide(JavaLexer.SL_COMMENT);
440: filter.hide(JavaLexer.ML_COMMENT);
441:
442: // Create a parser that reads from the scanner
443: // JavaRecognizer parser(lexer);
444: JavaRecognizer parser = new JavaRecognizer(filter);
445: parser
446: .setASTNodeClass(CommonASTWithLocationsAndHidden.class
447: .getName());
448:
449: //***********************************************************************
450: // Antlr 2.7.2
451: //***********************************************************************
452: // parser.setASTFactory(new ASTFactory())
453: // ASTFactory myFactory =
454: // new ASTFactory();
455: // antlr::ASTFactory my_factory("CommonASTWithLocationsAndHidden",
456: // &antlr::CommonASTWithLocationsAndHidden::factory);
457: // // tell the parser about the factory
458: // parser.setASTFactory(&my_factory);
459: //
460: // // let the parser initialize the factory
461: // parser.initializeFactory();
462: // parser.setASTNodeFactory(&my_factory);
463:
464: //***********************************************************************
465: // Antlr 2.7.1
466: //***********************************************************************
467: // parser.setASTFactory(CommonAST)
468: // parser.setASTNodeFactory(&antlr::CommonASTWithLocationsAndHidden::factory);
469:
470: if (filename != null)
471: parser.setFilename(filename);
472:
473: try {
474: // start parsing at the compilationUnit rule
475: parser.setEventController(m_EventController);
476: parser.compilationUnit();
477: } catch (ANTLRException e) {
478: m_EventController.errorFound(e.getMessage(), -1, -1,
479: filename);
480: } catch (Exception e) {
481: m_EventController.errorFound(e.getMessage(), -1, -1,
482: filename);
483: }
484:
485: // #if _DEBUG
486: //
487: // ASTUtilities::DumpTree(_T("c:\\TestDump.txt"), parser.getAST(), false);
488: // #endif
489:
490: boolean errorOccurred = false;
491: try {
492: // java.io.PrintStream curOut = System.out;
493: // PrintStream newOut = new PrintStream("C:\\Temp\\ASTDump.txt");
494: // System.setOut(newOut);
495: // antlr.DumpASTVisitor visitor = new antlr.DumpASTVisitor();
496: // visitor.visit(parser.getAST());
497: // newOut.flush();
498: // System.setOut(curOut);
499:
500: JavaTreeParser treeParser = new JavaTreeParser();
501: treeParser.setEventController(m_EventController);
502: treeParser.compilationUnit(parser.getAST());
503: } catch (ANTLRException e) {
504: m_EventController.errorFound(e.getMessage(), -1, -1,
505: filename);
506: } catch (Exception e) {
507: e.printStackTrace();
508: errorOccurred = true;
509: m_EventController.errorFound(e.getMessage(), -1, -1,
510: filename);
511: }
512:
513: if (errorOccurred) {
514: m_EventController
515: .errorFound(
516: "Unable to complete parsing the file. Possible Stack Overflow.",
517: -1, -1, filename);
518: }
519:
520: // The AST Tree will desctruct in a recursive mannor. When the
521: // tree is deep the descruction process can cause a stack overflow. To
522: // protect against the stack overflow DeleteTree will desctruct the AST
523: // tree in a non-recursive mannor.
524: // ASTUtilities astUtils = new ASTUt;
525: // astUtils.DeleteTree(parser.getAST());
526: } catch (Exception e) {
527: e.printStackTrace();
528: } finally {
529: m_EventController.clear();
530: }
531: }
532: }
|