1 12 13 package org.eclipse.ant.internal.ui.datatransfer; 14 15 import java.io.File ; 16 import com.ibm.icu.text.MessageFormat; 17 import java.util.ArrayList ; 18 import java.util.Iterator ; 19 import java.util.List ; 20 import java.util.Map ; 21 import java.util.Set ; 22 import java.util.TreeMap ; 23 import java.util.TreeSet ; 24 25 import org.eclipse.core.resources.IFile; 26 import org.eclipse.jdt.core.IClassFile; 27 import org.eclipse.jdt.core.IJavaProject; 28 import org.eclipse.jdt.core.JavaCore; 29 import org.eclipse.jdt.core.ToolFactory; 30 import org.eclipse.jdt.core.util.IClassFileReader; 31 import org.eclipse.jdt.core.util.IConstantPool; 32 import org.eclipse.jdt.core.util.IConstantPoolConstant; 33 import org.eclipse.jdt.core.util.IConstantPoolEntry; 34 import org.eclipse.jface.dialogs.MessageDialog; 35 import org.eclipse.swt.widgets.Shell; 36 37 41 public class SourceAnalyzer { 42 43 46 private SourceAnalyzer() { 47 48 } 49 50 59 public static void checkCycles(IJavaProject currentProject, 60 EclipseClasspath classpath, Shell shell) { 61 62 StringBuffer message = new StringBuffer (); 63 Map src2dir = new TreeMap (); Map srcdir2classes = new TreeMap (); 66 determineSources(currentProject, classpath, src2dir, srcdir2classes); 67 68 Map srcdir2sourcedirs = determineRequiredSrcDirs(src2dir, 69 srcdir2classes); 70 String projectName = currentProject.getProject().getName(); 71 72 List cycle = new ArrayList (); 73 if (isCyclic(srcdir2sourcedirs, cycle)) { 74 showCycleWarning(projectName, shell, cycle, message); 75 return; 76 } 77 78 checkBuildOrder(classpath, projectName, shell, srcdir2sourcedirs); 79 } 80 81 84 private static void determineSources(IJavaProject currentProject, 85 EclipseClasspath classpath, Map src2dir, Map srcdir2classes) { 86 87 for (int i = 0; i < classpath.srcDirs.size(); i++) { 88 String srcDir = (String ) classpath.srcDirs.get(i); 89 String classDir = (String ) classpath.classDirs.get(i); 90 if (EclipseClasspath.isReference(srcDir)) { 91 continue; 92 } 93 File dir; 94 if (srcDir.equals(".")) { dir = currentProject.getResource().getLocation().toFile(); 96 } else { 97 IFile file = currentProject.getProject().getFile(srcDir); 98 dir = file.getLocation().toFile(); 99 } 100 if (EclipseClasspath.isLinkedResource(srcDir)) { 101 String link = classpath.resolveLinkedResource(srcDir); 102 dir = new File (link); 103 } 104 Set sources = findFiles(dir, ".java"); 106 for (Iterator iter = sources.iterator(); iter.hasNext();) { 108 String srcFile = (String ) iter.next(); 109 src2dir.put(srcFile, srcDir); 110 IFile classFile = currentProject.getProject().getFile( 111 classDir + '/' + srcFile + ".class"); if (!classFile.exists()) { 113 continue; 115 } 116 Set classes = (Set ) srcdir2classes.get(srcDir); 117 if (classes == null) { 118 classes = new TreeSet (); 119 } 120 classes.addAll(getRequiredClasses(classFile)); 121 srcdir2classes.put(srcDir, classes); 122 } 123 } 124 } 125 126 133 private static Map determineRequiredSrcDirs(Map src2dir, Map srcdir2classes) { 134 135 Map srcdir2sourcedirs = new TreeMap (); for (Iterator iter = srcdir2classes.keySet().iterator(); iter.hasNext();) { 137 String srcDir = (String ) iter.next(); 138 Set classes = (Set ) srcdir2classes.get(srcDir); 139 for (Iterator iterator = classes.iterator(); iterator.hasNext();) { 140 String classname = (String ) iterator.next(); 141 String classsrc = (String ) src2dir.get(classname); 142 if (classsrc != null && !classsrc.equals(srcDir)) { 144 Set sourcedirs = (Set ) srcdir2sourcedirs.get(srcDir); 145 if (sourcedirs == null) { 146 sourcedirs = new TreeSet (); 147 } 148 sourcedirs.add(classsrc); 149 srcdir2sourcedirs.put(srcDir, sourcedirs); 150 } 151 } 152 } 153 return srcdir2sourcedirs; 154 } 155 156 private static void showCycleWarning(String projectName, Shell shell, 157 List cycle, StringBuffer message) { 158 159 String m = MessageFormat.format(DataTransferMessages.SourceAnalyzer_0, 160 new String [] { projectName }); 161 message.append(m); 162 message.append(ExportUtil.NEWLINE); 163 164 for (Iterator iter = cycle.iterator(); iter.hasNext();) { 166 String s = (String ) iter.next(); 167 s = EclipseClasspath.getLinkedResourceName(s); 168 message.append(s); 169 message.append(" -> "); } 171 message.append(EclipseClasspath.getLinkedResourceName((String ) cycle 172 .get(0))); 173 174 MessageDialog.openWarning(shell, DataTransferMessages.SourceAnalyzer_1, 175 message.toString()); 176 } 177 178 181 private static void checkBuildOrder(EclipseClasspath classpath, 182 String projectName, Shell shell, Map srcdir2sourcedirs) { 183 184 for (Iterator iter = srcdir2sourcedirs.keySet().iterator(); iter 185 .hasNext();) { 186 String srcdir = (String ) iter.next(); 187 Set sourcedirs = (Set ) srcdir2sourcedirs.get(srcdir); 188 int classpathIndex = classpath.srcDirs.indexOf(srcdir); 189 for (Iterator iterator = sourcedirs.iterator(); iterator.hasNext();) { 190 String requiredSrc = (String ) iterator.next(); 191 int i = classpath.srcDirs.indexOf(requiredSrc); 192 if (i > classpathIndex) { 194 String s = MessageFormat.format( 195 DataTransferMessages.SourceAnalyzer_3, 196 new String [] { projectName }); 197 198 MessageDialog.openWarning(shell, 199 DataTransferMessages.SourceAnalyzer_2, s 200 + ExportUtil.NEWLINE + requiredSrc 201 + " <-> " + srcdir + ExportUtil.NEWLINE); 203 break; 204 } 205 } 206 } 207 } 208 209 217 public static Set getRequiredClasses(IFile file) { 218 219 Set classes = new TreeSet (); 220 IClassFile classFile = JavaCore.createClassFileFrom(file); 221 IClassFileReader reader = ToolFactory.createDefaultClassFileReader( 222 classFile, IClassFileReader.CONSTANT_POOL); 223 if (reader == null) { 224 return classes; 226 } 227 IConstantPool pool = reader.getConstantPool(); 228 for (int i = 0; i < pool.getConstantPoolCount(); i++) { 229 if (pool.getEntryKind(i) == IConstantPoolConstant.CONSTANT_Class) { 230 IConstantPoolEntry entry = pool.decodeEntry(i); 231 String classname = new String (entry.getClassInfoName()); 232 int index = classname.indexOf('$'); 234 if (index != -1) { 235 classname = classname.substring(0, index); 236 } 237 classes.add(classname); 238 } 239 } 240 return classes; 241 } 242 243 253 public static Set findFiles(File dir, String extension) { 254 255 Set visited = new TreeSet (); 256 findFiles(dir, dir, extension, visited); 257 return visited; 258 } 259 260 private static void findFiles(File base, File dir, String extension, 261 Set visited) { 262 263 if (dir.isDirectory()) { 264 File [] children = dir.listFiles(); 265 for (int i = 0; i < children.length; i++) { 266 findFiles(base, children[i], extension, visited); 267 } 268 } else if (dir.getAbsolutePath().endsWith(extension)) { 269 String filename = ExportUtil.removePrefixAndSuffix(dir 271 .getAbsolutePath(), 272 base.getAbsolutePath() + File.separator, extension); 273 visited.add(filename.replace('\\', '/')); 274 } 275 } 276 277 286 private static boolean isCyclic(Map srcdir2sourcedirs, List cycle) { 287 288 return !isAcyclic(srcdir2sourcedirs, cycle); 289 } 290 291 private static boolean isAcyclic(Map srcdir2sourcedirs, List cycle) { 292 293 List visited = new ArrayList (); 295 List exited = new ArrayList (); 296 297 for (Iterator iter = srcdir2sourcedirs.keySet().iterator(); iter 298 .hasNext();) { 299 String srcdir = (String ) iter.next(); 300 if (!visited.contains(srcdir)) { 301 if (circleSearch(srcdir, srcdir2sourcedirs, visited, exited, 302 cycle)) { 303 return false; 304 } 305 } 306 } 307 return true; 308 } 309 310 private static boolean circleSearch(String srcdir, Map srcdir2sourcedirs, 311 List visited, List exited, List cycle) { 312 313 boolean res = false; 314 visited.add(srcdir); 315 cycle.add(srcdir); 316 317 Set sourcedirs = (Set ) srcdir2sourcedirs.get(srcdir); if (sourcedirs != null) { 319 for (Iterator iter = sourcedirs.iterator(); iter.hasNext();) { 320 String src = (String ) iter.next(); 321 if (!visited.contains(src)) { 322 res = circleSearch(src, srcdir2sourcedirs, visited, exited, 323 cycle); 324 } else if (!exited.contains(src)) { 325 res = true; 326 } 327 if (res) { 328 break; 329 } 330 } 331 } 332 if (!res) { 333 cycle.clear(); 334 } 335 exited.add(srcdir); 336 return res; 337 } 338 } 339 | Popular Tags |