1 12 package org.eclipse.jdt.internal.ui.jarpackager; 13 14 import java.io.ByteArrayInputStream ; 15 import java.io.ByteArrayOutputStream ; 16 import java.io.File ; 17 import java.io.IOException ; 18 import java.io.InputStream ; 19 import java.lang.reflect.InvocationTargetException ; 20 import java.net.URI ; 21 import java.util.ArrayList ; 22 import java.util.Arrays ; 23 import java.util.Collections ; 24 import java.util.HashMap ; 25 import java.util.HashSet ; 26 import java.util.Iterator ; 27 import java.util.List ; 28 import java.util.Map ; 29 import java.util.Set ; 30 import java.util.jar.Manifest ; 31 import java.util.zip.ZipException ; 32 33 import org.eclipse.core.filesystem.EFS; 34 import org.eclipse.core.runtime.CoreException; 35 import org.eclipse.core.runtime.IPath; 36 import org.eclipse.core.runtime.IProgressMonitor; 37 import org.eclipse.core.runtime.IStatus; 38 import org.eclipse.core.runtime.MultiStatus; 39 import org.eclipse.core.runtime.Status; 40 import org.eclipse.core.runtime.SubProgressMonitor; 41 42 import org.eclipse.core.resources.IContainer; 43 import org.eclipse.core.resources.IFile; 44 import org.eclipse.core.resources.IFolder; 45 import org.eclipse.core.resources.IMarker; 46 import org.eclipse.core.resources.IProject; 47 import org.eclipse.core.resources.IResource; 48 import org.eclipse.core.resources.IncrementalProjectBuilder; 49 import org.eclipse.core.resources.ResourcesPlugin; 50 51 import org.eclipse.swt.widgets.Shell; 52 53 import org.eclipse.jface.operation.ModalContext; 54 55 import org.eclipse.ui.actions.WorkspaceModifyOperation; 56 57 import org.eclipse.jdt.core.IClasspathEntry; 58 import org.eclipse.jdt.core.IJavaElement; 59 import org.eclipse.jdt.core.IJavaModelMarker; 60 import org.eclipse.jdt.core.IJavaProject; 61 import org.eclipse.jdt.core.IPackageFragment; 62 import org.eclipse.jdt.core.IPackageFragmentRoot; 63 import org.eclipse.jdt.core.IRegion; 64 import org.eclipse.jdt.core.ITypeRoot; 65 import org.eclipse.jdt.core.JavaCore; 66 import org.eclipse.jdt.core.JavaModelException; 67 import org.eclipse.jdt.core.ToolFactory; 68 import org.eclipse.jdt.core.util.IClassFileReader; 69 import org.eclipse.jdt.core.util.ISourceAttribute; 70 71 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 72 import org.eclipse.jdt.internal.corext.util.Messages; 73 import org.eclipse.jdt.internal.corext.util.Resources; 74 75 import org.eclipse.jdt.ui.StandardJavaElementContentProvider; 76 import org.eclipse.jdt.ui.jarpackager.IJarDescriptionWriter; 77 import org.eclipse.jdt.ui.jarpackager.IJarExportRunnable; 78 import org.eclipse.jdt.ui.jarpackager.JarPackageData; 79 import org.eclipse.jdt.ui.jarpackager.JarWriter3; 80 81 import org.eclipse.jdt.internal.ui.IJavaStatusConstants; 82 import org.eclipse.jdt.internal.ui.JavaPlugin; 83 import org.eclipse.jdt.internal.ui.refactoring.RefactoringSaveHelper; 84 import org.eclipse.jdt.internal.ui.util.BusyIndicatorRunnableContext; 85 86 89 public class JarFileExportOperation extends WorkspaceModifyOperation implements IJarExportRunnable { 90 91 private static class MessageMultiStatus extends MultiStatus { 92 MessageMultiStatus(String pluginId, int code, String message, Throwable exception) { 93 super(pluginId, code, message, exception); 94 } 95 98 protected void setMessage(String message) { 99 super.setMessage(message); 100 } 101 } 102 103 private JarWriter3 fJarWriter; 104 private JarPackageData fJarPackage; 105 private JarPackageData[] fJarPackages; 106 private Shell fParentShell; 107 private Map fJavaNameToClassFilesMap; 108 private IContainer fClassFilesMapContainer; 109 private Set fExportedClassContainers; 110 private MessageMultiStatus fStatus; 111 private StandardJavaElementContentProvider fJavaElementContentProvider; 112 private boolean fFilesSaved; 113 114 121 public JarFileExportOperation(JarPackageData jarPackage, Shell parent) { 122 this(new JarPackageData[] {jarPackage}, parent); 123 } 124 125 132 public JarFileExportOperation(JarPackageData[] jarPackages, Shell parent) { 133 this(parent); 134 fJarPackages= jarPackages; 135 } 136 137 private JarFileExportOperation(Shell parent) { 138 fParentShell= parent; 139 fStatus= new MessageMultiStatus(JavaPlugin.getPluginId(), IStatus.OK, "", null); fJavaElementContentProvider= new StandardJavaElementContentProvider(); 141 } 142 143 private void addToStatus(CoreException ex) { 144 IStatus status= ex.getStatus(); 145 String message= ex.getLocalizedMessage(); 146 if (message == null || message.length() < 1) { 147 message= JarPackagerMessages.JarFileExportOperation_coreErrorDuringExport; 148 status= new Status(status.getSeverity(), status.getPlugin(), status.getCode(), message, ex); 149 } 150 fStatus.add(status); 151 } 152 153 159 protected void addInfo(String message, Throwable error) { 160 fStatus.add(new Status(IStatus.INFO, JavaPlugin.getPluginId(), IJavaStatusConstants.INTERNAL_ERROR, message, error)); 161 } 162 163 169 private void addWarning(String message, Throwable error) { 170 fStatus.add(new Status(IStatus.WARNING, JavaPlugin.getPluginId(), IJavaStatusConstants.INTERNAL_ERROR, message, error)); 171 } 172 173 179 private void addError(String message, Throwable error) { 180 fStatus.add(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IJavaStatusConstants.INTERNAL_ERROR, message, error)); 181 } 182 183 188 private int countSelectedElements() { 189 Set enclosingJavaProjects= new HashSet (10); 190 int count= 0; 191 192 int n= fJarPackage.getElements().length; 193 for (int i= 0; i < n; i++) { 194 Object element= fJarPackage.getElements()[i]; 195 196 IJavaProject javaProject= getEnclosingJavaProject(element); 197 if (javaProject != null) 198 enclosingJavaProjects.add(javaProject); 199 200 IResource resource= null; 201 if (element instanceof IJavaElement) { 202 IJavaElement je= (IJavaElement)element; 203 try { 204 resource= je.getUnderlyingResource(); 205 } catch (JavaModelException ex) { 206 continue; 207 } 208 209 if (resource == null) 211 continue; 212 } 213 else 214 resource= (IResource)element; 215 if (resource != null) { 216 if (resource.getType() == IResource.FILE) 217 count++; 218 else 219 count+= getTotalChildCount((IContainer) resource); 220 } 221 } 222 223 if (fJarPackage.areOutputFoldersExported()) { 224 if (!fJarPackage.areJavaFilesExported()) 225 count= 0; 226 Iterator iter= enclosingJavaProjects.iterator(); 227 while (iter.hasNext()) { 228 IJavaProject javaProject= (IJavaProject)iter.next(); 229 IContainer[] outputContainers; 230 try { 231 outputContainers= getOutputContainers(javaProject); 232 } catch (CoreException ex) { 233 addToStatus(ex); 234 continue; 235 } 236 for (int i= 0; i < outputContainers.length; i++) 237 count += getTotalChildCount(outputContainers[i]); 238 239 } 240 } 241 242 return count; 243 } 244 245 private int getTotalChildCount(IContainer container) { 246 IResource[] members; 247 try { 248 members= container.members(); 249 } catch (CoreException ex) { 250 return 0; 251 } 252 int count= 0; 253 for (int i= 0; i < members.length; i++) { 254 if (members[i].getType() == IResource.FILE) 255 count++; 256 else 257 count += getTotalChildCount((IContainer)members[i]); 258 } 259 return count; 260 } 261 262 269 private void exportElement(Object element, IProgressMonitor progressMonitor) throws InterruptedException { 270 int leadSegmentsToRemove= 1; 271 IPackageFragmentRoot pkgRoot= null; 272 boolean isInJavaProject= false; 273 IResource resource= null; 274 ITypeRoot typeRootElement= null; 275 IJavaProject jProject= null; 276 if (element instanceof IJavaElement) { 277 isInJavaProject= true; 278 IJavaElement je= (IJavaElement)element; 279 if (!(je instanceof ITypeRoot)) { 280 exportJavaElement(progressMonitor, je); 281 return; 282 } 283 typeRootElement= (ITypeRoot) je; 284 jProject= typeRootElement.getJavaProject(); 285 pkgRoot= JavaModelUtil.getPackageFragmentRoot(je); 286 resource= typeRootElement.getResource(); 287 } else 288 resource= (IResource)element; 289 290 if (!resource.isAccessible()) { 291 addWarning(Messages.format(JarPackagerMessages.JarFileExportOperation_resourceNotFound, resource.getFullPath()), null); 292 return; 293 } 294 295 if (resource.getType() == IResource.FILE) { 296 if (!isInJavaProject) { 297 try { 299 isInJavaProject= resource.getProject().hasNature(JavaCore.NATURE_ID); 300 } catch (CoreException ex) { 301 addWarning(Messages.format(JarPackagerMessages.JarFileExportOperation_projectNatureNotDeterminable, resource.getFullPath()), ex); 302 return; 303 } 304 if (isInJavaProject) { 305 jProject= JavaCore.create(resource.getProject()); 306 try { 307 IPackageFragment pkgFragment= jProject.findPackageFragment(resource.getFullPath().removeLastSegments(1)); 308 if (pkgFragment != null) 309 pkgRoot= JavaModelUtil.getPackageFragmentRoot(pkgFragment); 310 else 311 pkgRoot= findPackageFragmentRoot(jProject, resource.getFullPath().removeLastSegments(1)); 312 } catch (JavaModelException ex) { 313 addWarning(Messages.format(JarPackagerMessages.JarFileExportOperation_javaPackageNotDeterminable, resource.getFullPath()), ex); 314 return; 315 } 316 } 317 } 318 319 if (pkgRoot != null && jProject != null) { 320 leadSegmentsToRemove= pkgRoot.getPath().segmentCount(); 321 boolean isOnBuildPath; 322 isOnBuildPath= jProject.isOnClasspath(resource); 323 if (!isOnBuildPath || (mustUseSourceFolderHierarchy() && !pkgRoot.getElementName().equals(IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH))) 324 leadSegmentsToRemove--; 325 } 326 327 IPath destinationPath= resource.getFullPath().removeFirstSegments(leadSegmentsToRemove); 328 329 boolean isInOutputFolder= false; 330 if (isInJavaProject && jProject != null) { 331 try { 332 isInOutputFolder= jProject.getOutputLocation().isPrefixOf(resource.getFullPath()); 333 } catch (JavaModelException ex) { 334 isInOutputFolder= false; 335 } 336 } 337 if (typeRootElement != null) { 338 exportClassFiles(progressMonitor, typeRootElement, destinationPath); 339 } 340 341 exportResource(progressMonitor, pkgRoot, isInJavaProject, resource, destinationPath, isInOutputFolder); 342 343 progressMonitor.worked(1); 344 ModalContext.checkCanceled(progressMonitor); 345 346 } else 347 exportContainer(progressMonitor, (IContainer)resource); 348 } 349 350 private void exportJavaElement(IProgressMonitor progressMonitor, IJavaElement je) throws InterruptedException { 351 if (je.getElementType() == IJavaElement.PACKAGE_FRAGMENT_ROOT && ((IPackageFragmentRoot)je).isArchive()) 352 return; 353 354 Object [] children= fJavaElementContentProvider.getChildren(je); 355 for (int i= 0; i < children.length; i++) 356 exportElement(children[i], progressMonitor); 357 } 358 359 private void exportResource(IProgressMonitor progressMonitor, IResource resource, int leadingSegmentsToRemove) throws InterruptedException { 360 if (resource instanceof IContainer) { 361 IContainer container= (IContainer)resource; 362 IResource[] children; 363 try { 364 children= container.members(); 365 } catch (CoreException e) { 366 addWarning(Messages.format(JarPackagerMessages.JarFileExportOperation_errorDuringExport, container.getFullPath()), e); 368 return; 369 } 370 for (int i= 0; i < children.length; i++) 371 exportResource(progressMonitor, children[i], leadingSegmentsToRemove); 372 } else if (resource instanceof IFile) { 373 try { 374 IPath destinationPath= resource.getFullPath().removeFirstSegments(leadingSegmentsToRemove); 375 progressMonitor.subTask(Messages.format(JarPackagerMessages.JarFileExportOperation_exporting, destinationPath.toString())); 376 fJarWriter.write((IFile)resource, destinationPath); 377 } catch (CoreException ex) { 378 Throwable realEx= ex.getStatus().getException(); 379 if (realEx instanceof ZipException && realEx.getMessage() != null && realEx.getMessage().startsWith("duplicate entry:")) addWarning(ex.getMessage(), realEx); 381 else 382 addToStatus(ex); 383 } finally { 384 progressMonitor.worked(1); 385 ModalContext.checkCanceled(progressMonitor); 386 } 387 } 388 } 389 390 private void exportContainer(IProgressMonitor progressMonitor, IContainer container) throws InterruptedException { 391 if (container.getType() == IResource.FOLDER && isOutputFolder((IFolder)container)) 392 return; 393 394 IResource[] children= null; 395 try { 396 children= container.members(); 397 } catch (CoreException exception) { 398 addWarning(Messages.format(JarPackagerMessages.JarFileExportOperation_errorDuringExport, container.getFullPath()), exception); 400 } 401 if (children != null) { 402 for (int i= 0; i < children.length; i++) 403 exportElement(children[i], progressMonitor); 404 } 405 } 406 407 private IPackageFragmentRoot findPackageFragmentRoot(IJavaProject jProject, IPath path) throws JavaModelException { 408 if (jProject == null || path == null || path.segmentCount() <= 0) 409 return null; 410 IPackageFragmentRoot pkgRoot= jProject.findPackageFragmentRoot(path); 411 if (pkgRoot != null) 412 return pkgRoot; 413 else 414 return findPackageFragmentRoot(jProject, path.removeLastSegments(1)); 415 } 416 417 private void exportResource(IProgressMonitor progressMonitor, IPackageFragmentRoot pkgRoot, boolean isInJavaProject, IResource resource, IPath destinationPath, boolean isInOutputFolder) { 418 419 if (fJarPackage.areClassFilesExported() && destinationPath.toString().equals("META-INF/MANIFEST.MF")) { if (fJarPackage.isManifestGenerated()) 422 addWarning(Messages.format(JarPackagerMessages.JarFileExportOperation_didNotAddManifestToJar, resource.getFullPath()), null); 423 return; 424 } 425 426 boolean isNonJavaResource= !isInJavaProject || pkgRoot == null; 427 boolean isInClassFolder= false; 428 try { 429 isInClassFolder= pkgRoot != null && !pkgRoot.isArchive() && pkgRoot.getKind() == IPackageFragmentRoot.K_BINARY; 430 } catch (JavaModelException ex) { 431 addWarning(Messages.format(JarPackagerMessages.JarFileExportOperation_cantGetRootKind, resource.getFullPath()), ex); 432 } 433 if ((fJarPackage.areClassFilesExported() && 434 ((isNonJavaResource || (pkgRoot != null && !isJavaFile(resource) && !isClassFile(resource))) 435 || isInClassFolder && isClassFile(resource))) 436 || (fJarPackage.areJavaFilesExported() && (isNonJavaResource || (pkgRoot != null && !isClassFile(resource)) || (isInClassFolder && isClassFile(resource) && !fJarPackage.areClassFilesExported())))) { 437 try { 438 progressMonitor.subTask(Messages.format(JarPackagerMessages.JarFileExportOperation_exporting, destinationPath.toString())); 439 fJarWriter.write((IFile) resource, destinationPath); 440 } catch (CoreException ex) { 441 Throwable realEx= ex.getStatus().getException(); 442 if (realEx instanceof ZipException && realEx.getMessage() != null && realEx.getMessage().startsWith("duplicate entry:")) addWarning(ex.getMessage(), realEx); 444 else 445 addToStatus(ex); 446 } 447 } 448 } 449 450 private boolean isOutputFolder(IFolder folder) { 451 try { 452 IJavaProject javaProject= JavaCore.create(folder.getProject()); 453 IPath outputFolderPath= javaProject.getOutputLocation(); 454 return folder.getFullPath().equals(outputFolderPath); 455 } catch (JavaModelException ex) { 456 return false; 457 } 458 } 459 460 private void exportClassFiles(IProgressMonitor progressMonitor, ITypeRoot typeRootElement, IPath destinationPath) { 461 if (fJarPackage.areClassFilesExported()) { 462 try { 463 if (!typeRootElement.exists()) 464 return; 465 466 Iterator iter= filesOnClasspath(typeRootElement, destinationPath, progressMonitor); 468 IPath baseDestinationPath= destinationPath.removeLastSegments(1); 469 while (iter.hasNext()) { 470 IFile file= (IFile)iter.next(); 471 IPath classFilePath= baseDestinationPath.append(file.getName()); 472 progressMonitor.subTask(Messages.format(JarPackagerMessages.JarFileExportOperation_exporting, classFilePath.toString())); 473 fJarWriter.write(file, classFilePath); 474 } 475 } catch (CoreException ex) { 476 addToStatus(ex); 477 } 478 } 479 } 480 481 486 private void exportSelectedElements(IProgressMonitor progressMonitor) throws InterruptedException { 487 fExportedClassContainers= new HashSet (10); 488 Set enclosingJavaProjects= new HashSet (10); 489 int n= fJarPackage.getElements().length; 490 for (int i= 0; i < n; i++) { 491 Object element= fJarPackage.getElements()[i]; 492 exportElement(element, progressMonitor); 493 if (fJarPackage.areOutputFoldersExported()) { 494 IJavaProject javaProject= getEnclosingJavaProject(element); 495 if (javaProject != null) 496 enclosingJavaProjects.add(javaProject); 497 } 498 } 499 if (fJarPackage.areOutputFoldersExported()) 500 exportOutputFolders(progressMonitor, enclosingJavaProjects); 501 } 502 503 private IJavaProject getEnclosingJavaProject(Object element) { 504 if (element instanceof IJavaElement) { 505 return ((IJavaElement)element).getJavaProject(); 506 } else if (element instanceof IResource) { 507 IProject project= ((IResource)element).getProject(); 508 try { 509 if (project.hasNature(JavaCore.NATURE_ID)) 510 return JavaCore.create(project); 511 } catch (CoreException ex) { 512 addWarning(Messages.format(JarPackagerMessages.JarFileExportOperation_projectNatureNotDeterminable, project.getFullPath()), ex); 513 } 514 } 515 return null; 516 } 517 518 private void exportOutputFolders(IProgressMonitor progressMonitor, Set javaProjects) throws InterruptedException { 519 if (javaProjects == null) 520 return; 521 522 Iterator iter= javaProjects.iterator(); 523 while (iter.hasNext()) { 524 IJavaProject javaProject= (IJavaProject)iter.next(); 525 IContainer[] outputContainers; 526 try { 527 outputContainers= getOutputContainers(javaProject); 528 } catch (CoreException ex) { 529 addToStatus(ex); 530 continue; 531 } 532 for (int i= 0; i < outputContainers.length; i++) 533 exportResource(progressMonitor, outputContainers[i], outputContainers[i].getFullPath().segmentCount()); 534 535 } 536 } 537 538 private IContainer[] getOutputContainers(IJavaProject javaProject) throws CoreException { 539 Set outputPaths= new HashSet (); 540 boolean includeDefaultOutputPath= false; 541 IPackageFragmentRoot[] roots= javaProject.getPackageFragmentRoots(); 542 for (int i= 0; i < roots.length; i++) { 543 if (roots[i] != null) { 544 IClasspathEntry cpEntry= roots[i].getRawClasspathEntry(); 545 if (cpEntry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { 546 IPath location= cpEntry.getOutputLocation(); 547 if (location != null) 548 outputPaths.add(location); 549 else 550 includeDefaultOutputPath= true; 551 } 552 } 553 } 554 555 if (includeDefaultOutputPath) { 556 outputPaths.add(javaProject.getOutputLocation()); 558 } 559 560 Set outputContainers= new HashSet (outputPaths.size()); 562 Iterator iter= outputPaths.iterator(); 563 while (iter.hasNext()) { 564 IPath path= (IPath)iter.next(); 565 if (javaProject.getProject().getFullPath().equals(path)) 566 outputContainers.add(javaProject.getProject()); 567 else { 568 IFolder outputFolder= createFolderHandle(path); 569 if (outputFolder == null || !outputFolder.isAccessible()) { 570 String msg= JarPackagerMessages.JarFileExportOperation_outputContainerNotAccessible; 571 addToStatus(new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IJavaStatusConstants.INTERNAL_ERROR, msg, null))); 572 } else 573 outputContainers.add(outputFolder); 574 } 575 } 576 return (IContainer[])outputContainers.toArray(new IContainer[outputContainers.size()]); 577 } 578 579 589 private Iterator filesOnClasspath(ITypeRoot typeRootElement, IPath pathInJar, IProgressMonitor progressMonitor) throws CoreException { 590 IFile file= (IFile) typeRootElement.getResource(); 591 IJavaProject javaProject= typeRootElement.getJavaProject(); 592 IPackageFragmentRoot pkgRoot= JavaModelUtil.getPackageFragmentRoot(typeRootElement); 593 594 IFile[] classFiles= fJarPackage.findClassfilesFor(file); 596 if (classFiles != null) 597 return Arrays.asList(classFiles).iterator(); 598 599 if (!isJavaFile(file)) 600 return Collections.EMPTY_LIST.iterator(); 601 602 IPath outputPath= null; 603 if (pkgRoot != null) { 604 IClasspathEntry cpEntry= pkgRoot.getRawClasspathEntry(); 605 if (cpEntry.getEntryKind() == IClasspathEntry.CPE_SOURCE) 606 outputPath= cpEntry.getOutputLocation(); 607 } 608 if (outputPath == null) 609 outputPath= javaProject.getOutputLocation(); 611 612 IContainer outputContainer; 613 if (javaProject.getProject().getFullPath().equals(outputPath)) 614 outputContainer= javaProject.getProject(); 615 else { 616 outputContainer= createFolderHandle(outputPath); 617 if (outputContainer == null || !outputContainer.isAccessible()) { 618 String msg= JarPackagerMessages.JarFileExportOperation_outputContainerNotAccessible; 619 throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IJavaStatusConstants.INTERNAL_ERROR, msg, null)); 620 } 621 } 622 623 boolean hasErrors= hasCompileErrors(file); 625 boolean hasWarnings= hasCompileWarnings(file); 626 boolean canBeExported= canBeExported(hasErrors, hasWarnings); 627 if (!canBeExported) 628 return Collections.EMPTY_LIST.iterator(); 629 reportPossibleCompileProblems(file, hasErrors, hasWarnings, canBeExported); 630 IContainer classContainer= outputContainer; 631 if (pathInJar.segmentCount() > 1) 632 classContainer= outputContainer.getFolder(pathInJar.removeLastSegments(1)); 633 634 if (fExportedClassContainers.contains(classContainer)) 635 return Collections.EMPTY_LIST.iterator(); 636 637 if (JavaCore.DO_NOT_GENERATE.equals(javaProject.getOption(JavaCore.COMPILER_SOURCE_FILE_ATTR, true))) { 638 IRegion region= JavaCore.newRegion(); 639 region.add(typeRootElement); 640 IResource[] generatedResources= JavaCore.getGeneratedResources(region, false); 641 if (generatedResources.length > 0) 642 return Arrays.asList(generatedResources).iterator(); 643 } 645 if (fClassFilesMapContainer == null || !fClassFilesMapContainer.equals(classContainer)) { 646 fJavaNameToClassFilesMap= buildJavaToClassMap(classContainer, progressMonitor); 647 if (fJavaNameToClassFilesMap == null) { 648 String containerName= classContainer.getFullPath().toString(); 650 String msg= Messages.format(JarPackagerMessages.JarFileExportOperation_missingSourceFileAttributeExportedAll, containerName); 651 addInfo(msg, null); 652 fExportedClassContainers.add(classContainer); 653 return getClassesIn(classContainer); 654 } 655 fClassFilesMapContainer= classContainer; 656 } 657 ArrayList classFileList= (ArrayList )fJavaNameToClassFilesMap.get(file.getName()); 658 if (classFileList == null || classFileList.isEmpty()) { 659 String msg= Messages.format(JarPackagerMessages.JarFileExportOperation_classFileOnClasspathNotAccessible, file.getFullPath()); 660 throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IJavaStatusConstants.INTERNAL_ERROR, msg, null)); 661 } 662 return classFileList.iterator(); 663 } 664 665 private Iterator getClassesIn(IContainer classContainer) throws CoreException { 666 IResource[] resources= classContainer.members(); 667 List files= new ArrayList (resources.length); 668 for (int i= 0; i < resources.length; i++) 669 if (resources[i].getType() == IResource.FILE && isClassFile(resources[i])) 670 files.add(resources[i]); 671 return files.iterator(); 672 } 673 674 682 private boolean isJavaFile(IResource file) { 683 return file != null 684 && file.getType() == IResource.FILE 685 && file.getFileExtension() != null 686 && JavaCore.isJavaLikeFileName(file.getName()); 687 } 688 689 696 private boolean isClassFile(IResource file) { 697 return file != null 698 && file.getType() == IResource.FILE 699 && file.getFileExtension() != null 700 && file.getFileExtension().equalsIgnoreCase("class"); } 702 703 707 private Map buildJavaToClassMap(IContainer container, IProgressMonitor monitor) throws CoreException { 708 if (container == null || !container.isAccessible()) 709 return new HashMap (0); 710 713 IClassFileReader cfReader= null; 714 IResource[] members= container.members(); 715 Map map= new HashMap (members.length); 716 for (int i= 0; i < members.length; i++) { 717 if (isClassFile(members[i])) { 718 IFile classFile= (IFile)members[i]; 719 URI location= classFile.getLocationURI(); 720 if (location != null) { 721 InputStream contents= null; 722 try { 723 contents= EFS.getStore(location).openInputStream(EFS.NONE, monitor); 724 cfReader= ToolFactory.createDefaultClassFileReader(contents, IClassFileReader.CLASSFILE_ATTRIBUTES); 725 } finally { 726 try { 727 if (contents != null) 728 contents.close(); 729 } catch (IOException e) { 730 throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IStatus.ERROR, 731 Messages.format(JarPackagerMessages.JarFileExportOperation_errorCannotCloseConnection, Resources.getLocationString(classFile)), 732 e)); 733 } 734 } 735 if (cfReader != null) { 736 ISourceAttribute sourceAttribute= cfReader.getSourceFileAttribute(); 737 if (sourceAttribute == null) { 738 743 addWarning(Messages.format( 744 JarPackagerMessages.JarFileExportOperation_classFileWithoutSourceFileAttribute, 745 Resources.getLocationString(classFile)), null); 746 return null; 747 } 748 String javaName= new String (sourceAttribute.getSourceFileName()); 749 Object classFiles= map.get(javaName); 750 if (classFiles == null) { 751 classFiles= new ArrayList (3); 752 map.put(javaName, classFiles); 753 } 754 ((ArrayList )classFiles).add(classFile); 755 } 756 } 757 } 758 } 759 return map; 760 } 761 762 768 private IFolder createFolderHandle(IPath folderPath) { 769 if (folderPath.isValidPath(folderPath.toString()) && folderPath.segmentCount() >= 2) 770 return JavaPlugin.getWorkspace().getRoot().getFolder(folderPath); 771 else 772 return null; 773 } 774 775 782 public IStatus getStatus() { 783 String message= null; 784 switch (fStatus.getSeverity()) { 785 case IStatus.OK: 786 message= ""; break; 788 case IStatus.INFO: 789 message= JarPackagerMessages.JarFileExportOperation_exportFinishedWithInfo; 790 break; 791 case IStatus.WARNING: 792 message= JarPackagerMessages.JarFileExportOperation_exportFinishedWithWarnings; 793 break; 794 case IStatus.ERROR: 795 if (fJarPackages.length > 1) 796 message= JarPackagerMessages.JarFileExportOperation_creationOfSomeJARsFailed; 797 else 798 message= JarPackagerMessages.JarFileExportOperation_jarCreationFailed; 799 break; 800 default: 801 message= ""; break; 804 } 805 fStatus.setMessage(message); 806 return fStatus; 807 } 808 809 private boolean canBeExported(boolean hasErrors, boolean hasWarnings) throws CoreException { 810 return (!hasErrors && !hasWarnings) 811 || (hasErrors && fJarPackage.areErrorsExported()) 812 || (hasWarnings && fJarPackage.exportWarnings()); 813 } 814 815 private void reportPossibleCompileProblems(IFile file, boolean hasErrors, boolean hasWarnings, boolean canBeExported) { 816 if (hasErrors) { 817 if (canBeExported) 818 addWarning(Messages.format(JarPackagerMessages.JarFileExportOperation_exportedWithCompileErrors, file.getFullPath()), null); 819 else 820 addWarning(Messages.format(JarPackagerMessages.JarFileExportOperation_notExportedDueToCompileErrors, file.getFullPath()), null); 821 } 822 if (hasWarnings) { 823 if (canBeExported) 824 addWarning(Messages.format(JarPackagerMessages.JarFileExportOperation_exportedWithCompileWarnings, file.getFullPath()), null); 825 else 826 addWarning(Messages.format(JarPackagerMessages.JarFileExportOperation_notExportedDueToCompileWarnings, file.getFullPath()), null); 827 } 828 } 829 830 838 protected void execute(IProgressMonitor progressMonitor) throws InvocationTargetException , InterruptedException { 839 int count= fJarPackages.length; 840 progressMonitor.beginTask("", count); try { 842 for (int i= 0; i < count; i++) { 843 SubProgressMonitor subProgressMonitor= new SubProgressMonitor(progressMonitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK); 844 fJarPackage= fJarPackages[i]; 845 if (fJarPackage != null) 846 singleRun(subProgressMonitor); 847 } 848 } finally { 849 progressMonitor.done(); 850 } 851 } 852 853 private void singleRun(IProgressMonitor progressMonitor) throws InvocationTargetException , InterruptedException { 854 try { 855 if (!preconditionsOK()) 856 throw new InvocationTargetException (null, JarPackagerMessages.JarFileExportOperation_jarCreationFailedSeeDetails); 857 int totalWork= countSelectedElements(); 858 if (fJarPackage.areGeneratedFilesExported() 859 && ((!isAutoBuilding() && fJarPackage.isBuildingIfNeeded()) 860 || (isAutoBuilding() && fFilesSaved))) { 861 int subMonitorTicks= totalWork/10; 862 totalWork += subMonitorTicks; 863 progressMonitor.beginTask("", totalWork); SubProgressMonitor subProgressMonitor= new SubProgressMonitor(progressMonitor, subMonitorTicks, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK); 865 buildProjects(subProgressMonitor); 866 } else 867 progressMonitor.beginTask("", totalWork); 869 fJarWriter= fJarPackage.createJarWriter3(fParentShell); 870 exportSelectedElements(progressMonitor); 871 if (getStatus().getSeverity() != IStatus.ERROR) { 872 progressMonitor.subTask(JarPackagerMessages.JarFileExportOperation_savingFiles); 873 saveFiles(); 874 } 875 } catch (CoreException ex) { 876 addToStatus(ex); 877 } finally { 878 try { 879 if (fJarWriter != null) 880 fJarWriter.close(); 881 } catch (CoreException ex) { 882 addToStatus(ex); 883 } 884 progressMonitor.done(); 885 } 886 } 887 888 private boolean preconditionsOK() { 889 if (!fJarPackage.areGeneratedFilesExported() && !fJarPackage.areJavaFilesExported()) { 890 addError(JarPackagerMessages.JarFileExportOperation_noExportTypeChosen, null); 891 return false; 892 } 893 if (fJarPackage.getElements() == null || fJarPackage.getElements().length == 0) { 894 addError(JarPackagerMessages.JarFileExportOperation_noResourcesSelected, null); 895 return false; 896 } 897 if (fJarPackage.getAbsoluteJarLocation() == null) { 898 addError(JarPackagerMessages.JarFileExportOperation_invalidJarLocation, null); 899 return false; 900 } 901 File targetFile= fJarPackage.getAbsoluteJarLocation().toFile(); 902 if (targetFile.exists() && !targetFile.canWrite()) { 903 addError(JarPackagerMessages.JarFileExportOperation_jarFileExistsAndNotWritable, null); 904 return false; 905 } 906 if (!fJarPackage.isManifestAccessible()) { 907 addError(JarPackagerMessages.JarFileExportOperation_manifestDoesNotExist, null); 908 return false; 909 } 910 if (!fJarPackage.isMainClassValid(new BusyIndicatorRunnableContext())) { 911 addError(JarPackagerMessages.JarFileExportOperation_invalidMainClass, null); 912 return false; 913 } 914 915 if (fParentShell != null) { 916 final boolean[] res= { false }; 917 fParentShell.getDisplay().syncExec(new Runnable () { 918 public void run() { 919 RefactoringSaveHelper refactoringSaveHelper= new RefactoringSaveHelper(RefactoringSaveHelper.SAVE_ALL_ALWAYS_ASK); 920 res[0]= refactoringSaveHelper.saveEditors(fParentShell); 921 fFilesSaved= refactoringSaveHelper.hasFilesSaved(); 922 } 923 }); 924 if (!res[0]) { 925 addError(JarPackagerMessages.JarFileExportOperation_fileUnsaved, null); 926 return false; 927 } 928 } 929 930 return true; 931 } 932 933 private void saveFiles() { 934 if (fJarPackage.areGeneratedFilesExported() && fJarPackage.isManifestGenerated() && fJarPackage.isManifestSaved()) { 936 try { 937 saveManifest(); 938 } catch (CoreException ex) { 939 addError(JarPackagerMessages.JarFileExportOperation_errorSavingManifest, ex); 940 } catch (IOException ex) { 941 addError(JarPackagerMessages.JarFileExportOperation_errorSavingManifest, ex); 942 } 943 } 944 945 if (fJarPackage.isDescriptionSaved()) { 947 try { 948 saveDescription(); 949 } catch (CoreException ex) { 950 addError(JarPackagerMessages.JarFileExportOperation_errorSavingDescription, ex); 951 } catch (IOException ex) { 952 addError(JarPackagerMessages.JarFileExportOperation_errorSavingDescription, ex); 953 } 954 } 955 } 956 957 private void saveDescription() throws CoreException, IOException { 958 if (fJarPackage.isManifestReused()) 960 fJarPackage.setGenerateManifest(false); 961 ByteArrayOutputStream objectStreamOutput= new ByteArrayOutputStream (); 962 IFile descriptionFile= fJarPackage.getDescriptionFile(); 963 String encoding= "UTF-8"; try { 965 encoding= descriptionFile.getCharset(true); 966 } catch (CoreException exception) { 967 JavaPlugin.log(exception); 968 } 969 IJarDescriptionWriter writer= fJarPackage.createJarDescriptionWriter(objectStreamOutput, encoding); 970 ByteArrayInputStream fileInput= null; 971 try { 972 writer.write(fJarPackage); 973 fileInput= new ByteArrayInputStream (objectStreamOutput.toByteArray()); 974 if (descriptionFile.isAccessible()) { 975 if (fJarPackage.allowOverwrite() || JarPackagerUtil.askForOverwritePermission(fParentShell, descriptionFile.getFullPath().toString())) 976 descriptionFile.setContents(fileInput, true, true, null); 977 } else 978 descriptionFile.create(fileInput, true, null); 979 } finally { 980 if (fileInput != null) 981 fileInput.close(); 982 if (writer != null) 983 writer.close(); 984 } 985 } 986 987 private void saveManifest() throws CoreException, IOException { 988 ByteArrayOutputStream manifestOutput= new ByteArrayOutputStream (); 989 Manifest manifest= fJarPackage.getManifestProvider().create(fJarPackage); 990 manifest.write(manifestOutput); 991 ByteArrayInputStream fileInput= new ByteArrayInputStream (manifestOutput.toByteArray()); 992 IFile manifestFile= fJarPackage.getManifestFile(); 993 if (manifestFile.isAccessible()) { 994 if (fJarPackage.allowOverwrite() || JarPackagerUtil.askForOverwritePermission(fParentShell, manifestFile.getFullPath().toString())) 995 manifestFile.setContents(fileInput, true, true, null); 996 } else 997 manifestFile.create(fileInput, true, null); 998 } 999 1000 private boolean isAutoBuilding() { 1001 return ResourcesPlugin.getWorkspace().getDescription().isAutoBuilding(); 1002 } 1003 1004 private void buildProjects(IProgressMonitor progressMonitor) { 1005 Set builtProjects= new HashSet (10); 1006 Object [] elements= fJarPackage.getElements(); 1007 for (int i= 0; i < elements.length; i++) { 1008 IProject project= null; 1009 Object element= elements[i]; 1010 if (element instanceof IResource) 1011 project= ((IResource)element).getProject(); 1012 else if (element instanceof IJavaElement) 1013 project= ((IJavaElement)element).getJavaProject().getProject(); 1014 if (project != null && !builtProjects.contains(project)) { 1015 try { 1016 project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, progressMonitor); 1017 } catch (CoreException ex) { 1018 String message= Messages.format(JarPackagerMessages.JarFileExportOperation_errorDuringProjectBuild, project.getFullPath()); 1019 addError(message, ex); 1020 } finally { 1021 builtProjects.add(project); 1023 } 1024 } 1025 } 1026 } 1027 1028 1036 private boolean hasCompileErrors(IResource resource) throws CoreException { 1037 IMarker[] problemMarkers= resource.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE); 1038 for (int i= 0; i < problemMarkers.length; i++) { 1039 if (problemMarkers[i].getAttribute(IMarker.SEVERITY, -1) == IMarker.SEVERITY_ERROR) 1040 return true; 1041 } 1042 return false; 1043 } 1044 1045 1053 private boolean hasCompileWarnings(IResource resource) throws CoreException { 1054 IMarker[] problemMarkers= resource.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE); 1055 for (int i= 0; i < problemMarkers.length; i++) { 1056 if (problemMarkers[i].getAttribute(IMarker.SEVERITY, -1) == IMarker.SEVERITY_WARNING) 1057 return true; 1058 } 1059 return false; 1060 } 1061 1062 private boolean mustUseSourceFolderHierarchy() { 1063 return fJarPackage.useSourceFolderHierarchy() && fJarPackage.areJavaFilesExported() && !fJarPackage.areGeneratedFilesExported(); 1064 } 1065} 1066 | Popular Tags |