KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > debug > core > hcr > CompilationUnitDelta


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.debug.core.hcr;
12
13
14 import java.io.BufferedReader JavaDoc;
15 import java.io.IOException JavaDoc;
16 import java.io.InputStream JavaDoc;
17 import java.io.InputStreamReader JavaDoc;
18
19 import org.eclipse.core.resources.IFile;
20 import org.eclipse.core.resources.IFileState;
21 import org.eclipse.core.resources.ResourcesPlugin;
22 import org.eclipse.core.runtime.CoreException;
23 import org.eclipse.jdt.core.ICompilationUnit;
24 import org.eclipse.jdt.core.dom.AST;
25 import org.eclipse.jdt.core.dom.ASTMatcher;
26 import org.eclipse.jdt.core.dom.ASTParser;
27 import org.eclipse.jdt.core.dom.CompilationUnit;
28 import org.eclipse.jdt.core.dom.MethodDeclaration;
29
30 /**
31  * A <code>CompilationUnitDelta</code> represents the source code changes between
32  * a CU in the workspace and the same CU at some point in the past
33  * (from the local history).
34  * <p>
35  * This functionality is used in the context of Hot Code Replace
36  * to determine which stack frames are affected (and need to be dropped)
37  * by a class reload in the Java VM.
38  * <p>
39  * Typically a <code>CompilationUnitDelta</code> object is generated for a CU
40  * when the associated class is replaced in the VM.
41  */

42 public class CompilationUnitDelta {
43     
44     /**
45      * AST of the current source code
46      */

47     private CompilationUnit fCurrentAst;
48     /**
49      * AST of the previous source code
50      */

51     private CompilationUnit fPrevAst;
52     
53     /**
54      * AST parser
55      */

56     private ASTParser fParser = null;
57     
58     /**
59      * AST matcher
60      */

61     private ASTMatcher fMatcher = null;
62     
63     private boolean fHasHistory= false;
64     
65     /**
66      * Creates a new <code>CompilationUnitDelta object that calculates and stores
67      * the changes of the given CU since some point in time.
68      */

69     public CompilationUnitDelta(ICompilationUnit cu, long timestamp) throws CoreException {
70         
71         if (cu.isWorkingCopy()) {
72             cu= cu.getPrimary();
73         }
74         
75         // find underlying file
76
IFile file= (IFile) cu.getUnderlyingResource();
77
78         // get available editions
79
IFileState[] states= file.getHistory(null);
80         if (states == null || states.length <= 0) {
81             return;
82         }
83         fHasHistory= true;
84         
85         IFileState found= null;
86         // find edition just before the given time stamp
87
for (int i= 0; i < states.length; i++) {
88             IFileState state= states[i];
89             long d= state.getModificationTime();
90             if (d < timestamp) {
91                 found= state;
92                 break;
93             }
94         }
95         
96         if (found == null) {
97             found= states[states.length-1];
98         }
99         
100         InputStream JavaDoc oldContents= null;
101         InputStream JavaDoc newContents= null;
102         try {
103             oldContents= found.getContents();
104             newContents= file.getContents();
105         } catch (CoreException ex) {
106             return;
107         }
108         
109         fPrevAst = parse(oldContents, cu);
110         fCurrentAst = parse(newContents, cu);
111     }
112     
113     /**
114      * Returns <code>true</code>
115      * <ul>
116      * <li>if the source of the given member has been changed, or
117      * <li>if the element has been deleted, or
118      * <li>if the element has been newly created
119      * </ul>
120      * after the initial timestamp.
121      */

122     public boolean hasChanged(String JavaDoc methodName, String JavaDoc signature) {
123         if (!fHasHistory) {
124             return false; // optimistic: we have no history, so assume that member hasn't changed
125
}
126         if (fPrevAst == null || fCurrentAst == null) {
127             return true; // pessimistic: unable to build parse trees
128
}
129         MethodSearchVisitor visitor = new MethodSearchVisitor();
130         MethodDeclaration prev = findMethod(fPrevAst, visitor, methodName, signature);
131         if (prev != null) {
132             MethodDeclaration curr = findMethod(fCurrentAst, visitor, methodName, signature);
133             if (curr != null) {
134                 return !getMatcher().match(prev, curr);
135             }
136         }
137         return true;
138     }
139     
140     private MethodDeclaration findMethod(CompilationUnit cu, MethodSearchVisitor visitor, String JavaDoc name, String JavaDoc signature) {
141         visitor.setTargetMethod(name, signature);
142         cu.accept(visitor);
143         return visitor.getMatch();
144     }
145     
146     //---- private stuff ----------------------------------------------------------------
147

148     /**
149      * Parses the given input stream and returns a tree of JavaNodes
150      * or a null in case of failure.
151      */

152     private CompilationUnit parse(InputStream JavaDoc input, ICompilationUnit cu) {
153         
154         char[] buffer= readString(input);
155         if (buffer != null) {
156             if (fParser == null) {
157                 fParser = ASTParser.newParser(AST.JLS3);
158             }
159             fParser.setSource(buffer);
160             fParser.setProject(cu.getJavaProject());
161             fParser.setResolveBindings(true);
162             fParser.setKind(ASTParser.K_COMPILATION_UNIT);
163             fParser.setUnitName(cu.getElementName());
164             return (CompilationUnit) fParser.createAST(null);
165         }
166         return null;
167     }
168     
169     /**
170      * Returns an AST matcher
171      *
172      * @return AST matcher
173      */

174     private ASTMatcher getMatcher() {
175         if (fMatcher == null) {
176             fMatcher = new ASTMatcher();
177         }
178         return fMatcher;
179     }
180             
181     /**
182      * Returns null if an error occurred.
183      */

184     private char[] readString(InputStream JavaDoc is) {
185         if (is == null) {
186             return null;
187         }
188         BufferedReader JavaDoc reader= null;
189         try {
190             StringBuffer JavaDoc buffer= new StringBuffer JavaDoc();
191             char[] part= new char[2048];
192             int read= 0;
193             reader= new BufferedReader JavaDoc(new InputStreamReader JavaDoc(is, ResourcesPlugin.getEncoding()));
194
195             while ((read= reader.read(part)) != -1) {
196                 buffer.append(part, 0, read);
197             }
198             
199             char[] b= new char[buffer.length()];
200             buffer.getChars(0, b.length, b, 0);
201             return b;
202             
203         } catch (IOException JavaDoc ex) {
204         } finally {
205             if (reader != null) {
206                 try {
207                     reader.close();
208                 } catch (IOException JavaDoc ex) {
209                 }
210             }
211         }
212         return null;
213     }
214 }
215
Popular Tags