| package org.eclipse.indigo.tests.repos; |
| |
| import java.io.File; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.net.URISyntaxException; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import junit.framework.Test; |
| |
| import org.eclipse.core.runtime.OperationCanceledException; |
| import org.eclipse.equinox.p2.core.ProvisionException; |
| import org.eclipse.equinox.p2.metadata.IInstallableUnit; |
| import org.eclipse.equinox.p2.metadata.Version; |
| import org.eclipse.equinox.p2.query.IQueryResult; |
| |
| public class VersionChecking extends TestRepo { |
| |
| |
| private static final String EQUALS = "equals"; |
| private static final String STARTS_WITH = "startsWith"; |
| private static final int STARTWITH_MATCH_LENGTH = 5; |
| |
| /** |
| * The test setup in this suite method is atypical, but handy do to local |
| * testing from workbench. For production work, currently, the values are |
| * set in ant execute method. If/when converted to true JUnit tests, this |
| * suite method will need to be chaanged to a more typical form, and no |
| * value hard coded. |
| */ |
| public static Test suite() { |
| System.out.println("test version checking"); |
| VersionChecking test = new VersionChecking(); |
| test.setName("testVersionUniqness"); |
| test.setRepoURLToTest("file:///home/shared/webtools/testStagingRepo"); |
| test.setOutputDirectory("/home/davidw/temp"); |
| return test; |
| } |
| |
| public boolean testVersionUniqness() throws URISyntaxException, ProvisionException, OperationCanceledException, IOException { |
| IQueryResult<IInstallableUnit> allIUs = getAllIUs(); |
| analyzeVersionPatterns(allIUs); |
| return analyzeNonUniqueVersions(allIUs); |
| } |
| |
| private void analyzeVersionPatterns(IQueryResult<IInstallableUnit> allIUs) throws IOException { |
| |
| |
| |
| FileWriter outfileWriter = null; |
| File outfile = null; |
| String testDirName = getOutputDirectory(); |
| try { |
| outfile = new File(testDirName, "versionPatterns.txt"); |
| outfileWriter = new FileWriter(outfile); |
| System.out.println("output: " + outfile.getAbsolutePath()); |
| |
| |
| outfileWriter.write("Version qualifer patterns used in repository" + EOL + EOL); |
| outfileWriter.write("Repository ('repoURLToTest'): " + getRepoURLToTest() + EOL + EOL); |
| outfileWriter.write("(Exploratory report ... maybe eventually used to find typos, such as 'qualfer')" + EOL + EOL); |
| |
| List<String> allQualifiers = collectQualifiers(allIUs, outfileWriter); |
| |
| |
| |
| collapseSortedQualifiers(outfileWriter, allQualifiers); |
| |
| |
| } |
| finally { |
| if (outfileWriter != null) { |
| try { |
| outfileWriter.close(); |
| } |
| catch (IOException e) { |
| // would be weird |
| e.printStackTrace(); |
| } |
| } |
| } |
| } |
| |
| private void collapseSortedQualifiers(FileWriter outfileWriter, List<String> allQualifiers) throws IOException, Error { |
| String reference = null; |
| int refCount = 0; |
| String type = EQUALS; |
| Collections.sort(allQualifiers); |
| |
| outfileWriter.write(EOL + "Count of (sorted) patterns matching up to " + STARTWITH_MATCH_LENGTH + " characters." + EOL + EOL); |
| |
| for (String q : allQualifiers) { |
| if (reference == null) { |
| reference = q; |
| refCount = 1; |
| } |
| else { |
| if (reference.equals(q)) { |
| refCount++; |
| type = EQUALS; |
| } |
| else { |
| if (reference.length() == 0) { |
| reference = "[empty string]"; |
| outfileWriter.write(refCount + "\t" + type + "\t\t\t" + reference + EOL); |
| reference = q; |
| refCount = 1; |
| type = EQUALS; |
| } |
| else if (startsSimilar(reference, q)) { |
| refCount++; |
| type = STARTS_WITH; |
| } |
| else { |
| if (STARTS_WITH.equals(type)) { |
| outfileWriter.write(refCount + "\t" + type + "\t\t" + subsection(reference) + EOL); |
| } |
| else if (EQUALS.equals(type)) { |
| outfileWriter.write(refCount + "\t" + type + "\t\t\t" + reference + EOL); |
| } |
| else { |
| throw new Error(); |
| } |
| reference = q; |
| refCount = 1; |
| type = EQUALS; |
| } |
| } |
| } |
| |
| } |
| } |
| |
| private List<String> collectQualifiers(IQueryResult<IInstallableUnit> allIUs, FileWriter outfileWriter) throws IOException, Error { |
| List<String> allQualifiers = new ArrayList(); |
| int nonOSGiCompatible = 0; |
| int nLessThanFour = 0; |
| int nMoreThanFour = 0; |
| for (IInstallableUnit iu : allIUs.toUnmodifiableSet()) { |
| |
| // exclude categories, since they are (often) intended to work with same ID, multiple versions |
| boolean isCategory = "true".equals(iu.getProperty("org.eclipse.equinox.p2.type.category")); |
| |
| // we exclude these things in some other repo reports ... to improve focus ... but suspect not needed here. |
| // boolean isFragment = "true".equals(iu.getProperty("org.eclipse.equinox.p2.type.fragment")); |
| // !isFragment && !isFeatureGroup(iu) |
| if (!isCategory && !isSpecial(iu)) { |
| //String bundleId = iu.getId(); |
| Version bundleVersion = iu.getVersion(); |
| if (bundleVersion.isOSGiCompatible()) { |
| if (bundleVersion.getSegmentCount() == 4) { |
| Comparable qualifier = bundleVersion.getSegment(3); |
| if (qualifier instanceof String) { |
| String qString = (String) qualifier; |
| if (qString.length() == 0) { |
| outfileWriter.write("zero length 4th segment: " + iu.getId() + EOL); |
| } |
| allQualifiers.add(qString); |
| } |
| else { |
| throw new Error("Program Error"); |
| } |
| } |
| else if (bundleVersion.getSegmentCount() < 4) { |
| nLessThanFour++; |
| } |
| else if (bundleVersion.getSegmentCount() > 4) { |
| nMoreThanFour++; |
| } |
| } |
| else { |
| nonOSGiCompatible++; |
| } |
| } |
| |
| |
| } |
| |
| outfileWriter.write(EOL + "Number of nonOSGi compatible versions: " + nonOSGiCompatible + EOL); |
| outfileWriter.write(EOL + "Number with more than 4 segments: " + nMoreThanFour + EOL); |
| outfileWriter.write(EOL + "Number wtih less than 4 segments: " + nLessThanFour + EOL + EOL); |
| return allQualifiers; |
| } |
| |
| private boolean startsSimilar(String reference, String q) { |
| return (q.startsWith(subsection(reference))); |
| } |
| |
| private String subsection(String reference) { |
| // length = endOffset - startOffset; |
| |
| String result = reference; |
| if (reference.length() >= STARTWITH_MATCH_LENGTH) { |
| result = (reference.substring(0, STARTWITH_MATCH_LENGTH)); |
| } |
| return result; |
| |
| } |
| |
| private boolean analyzeNonUniqueVersions(IQueryResult<IInstallableUnit> allIUs) throws IOException { |
| Map bundles = tabulateNonUniqueIDs(allIUs); |
| FileWriter outfileWriter = null; |
| File outfile = null; |
| String testDirName = getOutputDirectory(); |
| try { |
| outfile = new File(testDirName, "nonUniqueVersions.txt"); |
| outfileWriter = new FileWriter(outfile); |
| System.out.println("output: " + outfile.getAbsolutePath()); |
| |
| |
| outfileWriter.write("Non Unique Versions used in repository" + EOL + EOL); |
| outfileWriter.write("Repository ('repoURLToTest'): " + getRepoURLToTest() + EOL + EOL); |
| |
| int nUnique = 0; |
| for (Object bundleId : bundles.keySet()) { |
| Set versionSet = (Set) bundles.get(bundleId); |
| if (versionSet.size() == 1) { |
| nUnique++; |
| } |
| else { |
| printId(outfileWriter, bundleId); |
| for (Object version : versionSet) { |
| printVersion(outfileWriter, version); |
| } |
| } |
| } |
| |
| outfileWriter.write(EOL + "Number of unique id-versions " + nUnique + EOL); |
| |
| // always return false (no error), for now ... eventually may be able to |
| // figure out some heuristic to return "error", such as if new, non-expected multiple versions |
| return false; |
| } |
| finally { |
| if (outfileWriter != null) { |
| try { |
| outfileWriter.close(); |
| } |
| catch (IOException e) { |
| // would be weird |
| e.printStackTrace(); |
| } |
| } |
| } |
| } |
| |
| |
| private Map tabulateNonUniqueIDs(IQueryResult<IInstallableUnit> allIUs) { |
| Map bundles = new HashMap(); |
| for (IInstallableUnit iu : allIUs.toUnmodifiableSet()) { |
| try { |
| // exclude categories, since they are (often) intended to work with same ID, multiple versions |
| boolean isCategory = "true".equals(iu.getProperty("org.eclipse.equinox.p2.type.category")); |
| |
| // we exclude these things in some other repo reports ... to improve focus ... but suspect not needed here. |
| //boolean isFragment = "true".equals(iu.getProperty("org.eclipse.equinox.p2.type.fragment")); |
| // && !isSpecial(iu) && !isFragment && !isFeatureGroup(iu) |
| if (!isCategory) { |
| String bundleId = iu.getId(); |
| Version bundleVersion = iu.getVersion(); |
| // if bundle ID is already in map, we must have already found at least one |
| if (bundles.containsKey(bundleId)) { |
| Set versionSet = (Set) bundles.get(bundleId); |
| versionSet.add(bundleVersion); |
| } |
| else { |
| // haven't found one yet, so add it, with initial set of its (one) version |
| Set versionSet = new HashSet(); |
| versionSet.add(bundleVersion); |
| bundles.put(bundleId, versionSet); |
| } |
| |
| |
| } |
| |
| } |
| catch (RuntimeException e) { |
| e.printStackTrace(); |
| } |
| } |
| return bundles; |
| } |
| |
| private void printId(FileWriter out, Object id) throws IOException { |
| out.write(id + EOL); |
| } |
| |
| private void printVersion(FileWriter out, Object version) throws IOException { |
| out.write("\t" + version + EOL); |
| } |
| |
| } |