Skip to content

Commit

Permalink
Make order of elements in saved JAR description file deterministic #1024
Browse files Browse the repository at this point in the history


When exporting JAR description files from the JarPackageWizard, the
elements to be exported into the JAR file are currently stored in a
non-deterministic order. This makes it particularly difficult to merge
the description files in case they are put under version control.

This change makes a JAR description file exported from the
JarPackageWizard always list the exported elements in the same order by
sorting them according to their names. It also adds an according
regression test.

Fixes #1024
  • Loading branch information
HeikoKlare authored and iloveeclipse committed Dec 21, 2023
1 parent 440d8b0 commit 0972fd9
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,26 @@
*******************************************************************************/
package org.eclipse.jdt.ui.tests.dialogs;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

import java.io.InputStream;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Collections;
import java.util.UUID;

import org.eclipse.jdt.testplugin.JavaProjectHelper;
import org.eclipse.jdt.testplugin.util.DialogCheck;

import org.eclipse.swt.widgets.Shell;

import org.eclipse.core.runtime.CoreException;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;

import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.wizard.WizardDialog;

Expand All @@ -30,6 +45,9 @@
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;

import org.eclipse.jdt.ui.jarpackager.JarPackageData;

import org.eclipse.jdt.internal.ui.jarpackager.JarPackageReader;
import org.eclipse.jdt.internal.ui.jarpackager.JarPackageWizard;
import org.eclipse.jdt.internal.ui.wizards.JavaProjectWizard;
import org.eclipse.jdt.internal.ui.wizards.NewAnnotationCreationWizard;
Expand All @@ -55,6 +73,7 @@ public static Test suite() {
suite.addTest(new WizardsTest("testNewProjectWizard"));
suite.addTest(new WizardsTest("testPackageWizard"));
suite.addTest(new WizardsTest("testSourceFolderWizard"));
suite.addTest(new WizardsTest("testJarPackageWizard_sameElementOrderInJarDescriptionExports"));
return suite;
}

Expand Down Expand Up @@ -173,5 +192,69 @@ public void testJarPackageWizard() throws Exception {
JavaProjectHelper.delete(jproject);
}

public void testJarPackageWizard_sameElementOrderInJarDescriptionExports() throws Exception {
IResource[] roots = createProjectsWithSourceFolders(20);
IProject outputProject = roots[0].getProject();

IFile jardescProperOrder = outputProject.getFile("proper.jardesc");
exportJardesc(outputProject, roots).move(jardescProperOrder.getFullPath(), true, null);

IFile jardescReverseOrder = outputProject.getFile("reverse.jardesc");
Collections.reverse(Arrays.asList(roots));
exportJardesc(outputProject, roots).move(jardescReverseOrder.getFullPath(), true, null);

IFile jardescRewritten= outputProject.getFile("rewritten.jardesc");
JarPackageData packageData = new JarPackageData();
try (InputStream packageDataFileStream = Files.newInputStream(jardescReverseOrder.getLocation().toPath())) {
new JarPackageReader(packageDataFileStream).read(packageData);
}
exportJardesc(outputProject, packageData).move(jardescRewritten.getFullPath(), true, null);

assertThat("JAR descriptions written for elements in original and reverse order differ", Files.readString(jardescProperOrder.getLocation().toPath()),
is(Files.readString(jardescReverseOrder.getLocation().toPath())));
assertThat("original and rewritten JAR descriptions differ", Files.readString(jardescProperOrder.getLocation().toPath()), is(Files.readString(jardescRewritten.getLocation().toPath())));

for (IResource root : roots) {
JavaProjectHelper.delete(root.getProject());
}
}

private IResource[] createProjectsWithSourceFolders(int numberOfProjects) throws CoreException {
String binFolderName = "bin";
String sourceFolderName = "src";
IResource[] roots = new IResource[numberOfProjects];
for (int projectNumber = 0 ; projectNumber < numberOfProjects; projectNumber++) {
IJavaProject project= JavaProjectHelper.createJavaProject(UUID.randomUUID().toString(), binFolderName);
roots[projectNumber] = JavaProjectHelper.addSourceContainer(project, sourceFolderName).getResource();
}
return roots;
}

private IFile exportJardesc(IProject projectForExport, IResource[] exportElements) throws CoreException {
JarPackageData data = new JarPackageData();
data.setElements(exportElements);
return exportJardesc(projectForExport, data);
}

private IFile exportJardesc(IProject projectForExport, JarPackageData data) throws CoreException {
IFile exportFile = projectForExport.getFile("export.jar");
data.setJarLocation(exportFile.getLocation());
IFile jardescFile = projectForExport.getFile("save.jardesc");
data.setDescriptionLocation(jardescFile.getFullPath());
data.setSaveDescription(true);

JarPackageWizard wizard = new JarPackageWizard();
wizard.init(getWorkbench(), data);
wizard.setForcePreviousAndNextButtons(true);
WizardDialog dialog = new WizardDialog(getShell(), wizard);
dialog.create();
boolean exportSuccessful = wizard.performFinish();

exportFile.delete(true, null);
assertTrue("wizard did not finish successfully: " + wizard, exportSuccessful);
assertTrue("JAR description file was not created", jardescFile.exists());
return jardescFile;
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@
*******************************************************************************/
package org.eclipse.jdt.internal.ui.jarpackager;

import static java.util.Arrays.sort;
import static java.util.Comparator.comparing;

import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Objects;
import java.util.Set;

import org.eclipse.swt.SWT;
Expand Down Expand Up @@ -663,7 +667,9 @@ public void setPreviousPage(IWizardPage page) {
Object[] getSelectedElementsWithoutContainedChildren() {
Set<Object> closure= removeContainedChildren(fInputGroup.getWhiteCheckedTreeItems());
closure.addAll(getExportedNonContainers());
return closure.toArray();
Object[] sortedElements = closure.toArray();
sort(sortedElements, comparing(Objects::toString));
return sortedElements;
}

private Set<Object> removeContainedChildren(Set<Object> elements) {
Expand Down

0 comments on commit 0972fd9

Please sign in to comment.