diff options
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.updatesite')
4 files changed, 228 insertions, 2 deletions
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.updatesite/META-INF/MANIFEST.MF index a07ca0c58..6aea12f30 100644 --- a/bundles/org.eclipse.equinox.p2.updatesite/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.equinox.p2.updatesite/META-INF/MANIFEST.MF @@ -18,6 +18,7 @@ Import-Package: javax.xml.parsers, org.eclipse.equinox.app;version="1.1.0", org.eclipse.equinox.internal.p2.artifact.repository.simple, org.eclipse.equinox.internal.p2.core.helpers, + org.eclipse.equinox.internal.p2.metadata, org.eclipse.equinox.internal.p2.publisher.eclipse, org.eclipse.equinox.internal.p2.repository, org.eclipse.equinox.p2.core;version="[2.0.0,3.0.0)", diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/CategoryParser.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/CategoryParser.java index ece98b7db..e8a94ecb0 100644 --- a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/CategoryParser.java +++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/CategoryParser.java @@ -47,6 +47,7 @@ public class CategoryParser extends DefaultHandler { private static final String EXPRESSION = "expression"; //$NON-NLS-1$ private static final String PARAM = "param"; //$NON-NLS-1$ private static final String REPOSITORY_REF = "repository-reference"; //$NON-NLS-1$ + private static final String STATS_URI = "stats"; //$NON-NLS-1$ private static final int STATE_ARCHIVE = 3; private static final int STATE_CATEGORY = 4; @@ -63,6 +64,7 @@ public class CategoryParser extends DefaultHandler { private static final int STATE_QUERY = 11; private static final int STATE_SITE = 1; private static final int STATE_REPOSITORY_REF = 13; + private static final int STATE_STATS = 14; private boolean DESCRIPTION_SITE_ALREADY_SEEN = false; // Current object stack (used to hold the current object we are @@ -245,6 +247,11 @@ public class CategoryParser extends DefaultHandler { // do not pop object as we did not push the reference break; + case STATE_STATS : + stateStack.pop(); + // do not pop object stack because we didn't push anything + break; + case STATE_DESCRIPTION_SITE : stateStack.pop(); text = ""; //$NON-NLS-1$ @@ -392,6 +399,9 @@ public class CategoryParser extends DefaultHandler { case STATE_REPOSITORY_REF : return "Repository Reference"; //$NON-NLS-1$ + case STATE_STATS : + return "Stats Repository"; //$NON-NLS-1$ + default : return Messages.DefaultSiteParser_UnknownState; } @@ -472,6 +482,20 @@ public class CategoryParser extends DefaultHandler { } else if (elementName.equals(REPOSITORY_REF)) { stateStack.push(new Integer(STATE_REPOSITORY_REF)); processRepositoryReference(attributes); + } else if (elementName.equals(STATS_URI)) { + stateStack.push(new Integer(STATE_STATS)); + processStatsInfo(attributes); + } else + internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())}))); + } + + private void handleStatsState(String elementName, Attributes attributes) { + if (elementName.equals(FEATURE)) { + stateStack.push(STATE_FEATURE); + processStatsFeature(attributes); + } else if (elementName.equals(BUNDLE)) { + stateStack.push(STATE_BUNDLE); + processStatsBundle(attributes); } else internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())}))); } @@ -648,12 +672,83 @@ public class CategoryParser extends DefaultHandler { } catch (URISyntaxException e) { // UI should have already caught this } + } + + /* + * process stats top level element + */ + private void processStatsInfo(Attributes attributes) { + String location = attributes.getValue("location"); //$NON-NLS-1$ + try { + // One final validation but UI should have already done this. + URIUtil.fromString(location); + SiteModel site = (SiteModel) objectStack.peek(); + site.setStatsURIString(location); + } catch (URISyntaxException e) { + // Ignore if not valid. + } if (Tracing.DEBUG_GENERATOR_PARSING) debug("End processing Repository Reference: location:" + location); //$NON-NLS-1$ } /* + * process stats feature artifact + */ + private void processStatsFeature(Attributes attributes) { + SiteFeature feature = new SiteFeature(); + + // identifier and version + String id = attributes.getValue("id"); //$NON-NLS-1$ + String ver = attributes.getValue("version"); //$NON-NLS-1$ + + boolean noId = (id == null || id.trim().equals("")); //$NON-NLS-1$ + + // We need to have id and version, or the url, or both. + if (noId) + internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"url", getState(currentState())}))); //$NON-NLS-1$ + + feature.setFeatureIdentifier(id); + feature.setFeatureVersion(ver); + + SiteModel site = (SiteModel) objectStack.peek(); + site.addStatsFeature(feature); + objectStack.push(feature); + feature.setSiteModel(site); + + if (Tracing.DEBUG_GENERATOR_PARSING) + debug("End Processing Stats Feature Tag: id:" + id + " version:" + ver); //$NON-NLS-1$ //$NON-NLS-2$ } + } + + /* + * process stats bundle artifact info + */ + private void processStatsBundle(Attributes attributes) { + SiteBundle bundle = new SiteBundle(); + + // identifier and version + String id = attributes.getValue("id"); //$NON-NLS-1$ + String ver = attributes.getValue("version"); //$NON-NLS-1$ + + boolean noId = (id == null || id.trim().equals("")); //$NON-NLS-1$ + + // We need to have id and version, or the url, or both. + if (noId) + internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"url", getState(currentState())}))); //$NON-NLS-1$ + + bundle.setBundleIdentifier(id); + bundle.setBundleVersion(ver); + + SiteModel site = (SiteModel) objectStack.peek(); + site.addStatsBundle(bundle); + objectStack.push(bundle); + bundle.setSiteModel(site); + + if (Tracing.DEBUG_GENERATOR_PARSING) + debug("End Processing Stats Bundle Tag: id:" + id + " version:" + ver); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /* * process feature info */ private void processFeature(Attributes attributes) { @@ -857,6 +952,10 @@ public class CategoryParser extends DefaultHandler { handleSiteState(localName, attributes); break; + case STATE_STATS : + handleStatsState(localName, attributes); + break; + default : internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownStartState, (new String[] {getState(currentState())}))); break; diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteModel.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteModel.java index d2c1c2cbf..087659606 100644 --- a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteModel.java +++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteModel.java @@ -38,6 +38,7 @@ public class SiteModel { private URI locationURI; private String locationURIString; private String mirrorsURIString; + private String statsURIString; private boolean supportsPack200; private String type; private URLEntry[] associateSites; @@ -45,6 +46,8 @@ public class SiteModel { private List<String> messageKeys; private Map<Locale, Map<String, String>> localizations; private List<RepositoryReference> repositoryReferences; + private List<SiteFeature> statsFeatures; + private List<SiteBundle> statsBundles; /** * Creates an uninitialized site model object. @@ -107,6 +110,28 @@ public class SiteModel { } /** + * Adds a feature reference model to site stats artifacts. + * + * @param featureReference feature reference model + */ + public void addStatsFeature(SiteFeature featureReference) { + if (this.statsFeatures == null) + this.statsFeatures = new ArrayList<SiteFeature>(); + this.statsFeatures.add(featureReference); + } + + /** + * Adds a bundle reference model to site stats artifacts + * + * @param bundleReference bundle reference model + */ + public void addStatsBundle(SiteBundle bundleReference) { + if (this.statsBundles == null) + this.statsBundles = new ArrayList<SiteBundle>(); + this.statsBundles.add(bundleReference); + } + + /** * Adds a iu model to site. * * @param iu iu model @@ -199,6 +224,28 @@ public class SiteModel { } /** + * Returns an array of feature reference models for stats on this site. + * + * @return an array of feature reference models, or an empty array. + */ + public SiteFeature[] getStatsFeatures() { + if (statsFeatures == null || statsFeatures.size() == 0) + return new SiteFeature[0]; + return statsFeatures.toArray(new SiteFeature[0]); + } + + /** + * Returns an array of bundle reference models for stats on this site. + * + * @return an array of bundle reference models, or an empty array. + */ + public SiteBundle[] getStatsBundles() { + if (statsBundles == null || statsBundles.size() == 0) + return new SiteBundle[0]; + return statsBundles.toArray(new SiteBundle[0]); + } + + /** * Returns an array of IU models on this site. * * @return an array of IU models, or an empty array. @@ -221,6 +268,15 @@ public class SiteModel { } /** + * Returns the URI of the stats repository that tracks downloads. + * + * @return a String representation of the stats URI. + */ + public String getStatsURI() { + return statsURIString; + } + + /** * Gets the localizations for the site as a map from locale * to the set of translated properties for that locale. * @@ -379,4 +435,13 @@ public class SiteModel { return digestURIString; } + /** + * Sets the URI of the stats repository used to track downloads. + * + * @param statsURI a String describing the stats URI + */ + public void setStatsURIString(String statsURI) { + this.statsURIString = statsURI; + } + } diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteXMLAction.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteXMLAction.java index df31e3062..965110269 100644 --- a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteXMLAction.java +++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteXMLAction.java @@ -26,10 +26,12 @@ import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescriptio import org.eclipse.equinox.p2.metadata.expression.ExpressionUtil; import org.eclipse.equinox.p2.metadata.expression.IExpression; import org.eclipse.equinox.p2.publisher.*; -import org.eclipse.equinox.p2.publisher.eclipse.URLEntry; +import org.eclipse.equinox.p2.publisher.eclipse.*; import org.eclipse.equinox.p2.query.*; import org.eclipse.equinox.p2.repository.IRepository; import org.eclipse.equinox.p2.repository.IRepositoryReference; +import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor; +import org.eclipse.equinox.p2.repository.artifact.spi.ArtifactDescriptor; import org.eclipse.equinox.p2.repository.spi.RepositoryReference; import org.eclipse.equinox.spi.p2.publisher.LocalizationHelper; import org.eclipse.equinox.spi.p2.publisher.PublisherHelper; @@ -40,6 +42,8 @@ import org.eclipse.equinox.spi.p2.publisher.PublisherHelper; */ public class SiteXMLAction extends AbstractPublisherAction { static final private String QUALIFIER = "qualifier"; //$NON-NLS-1$ + static final private String P_STATS_URI = "p2.statsURI"; //$NON-NLS-1$ + static final private String P_STATS_MARKER = "download.stats"; //$NON-NLS-1$ private static final VersionSuffixGenerator versionSuffixGenerator = new VersionSuffixGenerator(); protected UpdateSite updateSite; private SiteCategory defaultCategory; @@ -99,7 +103,57 @@ public class SiteXMLAction extends AbstractPublisherAction { } initialize(); initializeRepoFromSite(publisherInfo); - return generateCategories(publisherInfo, results, monitor); + IStatus markingStats = markStatsArtifacts(publisherInfo, results, monitor); + if (markingStats.isOK()) { + return generateCategories(publisherInfo, results, monitor); + } + return markingStats; + } + + private IStatus markStatsArtifacts(IPublisherInfo publisherInfo, IPublisherResult results, IProgressMonitor monitor) { + SiteModel site = updateSite.getSite(); + // process all features listed and mark artifacts + SiteFeature[] features = site.getStatsFeatures(); + if (features != null) { + for (SiteFeature feature : features) { + if (monitor.isCanceled()) + return Status.CANCEL_STATUS; + Collection<IInstallableUnit> ius = getFeatureIU(feature, publisherInfo, results); + if (ius != null) { + for (IInstallableUnit iu : ius) { + IArtifactKey key = FeaturesAction.createFeatureArtifactKey(feature.getFeatureIdentifier(), iu.getVersion().toString()); + IArtifactDescriptor[] descriptors = publisherInfo.getArtifactRepository().getArtifactDescriptors(key); + if (descriptors.length > 0 && descriptors[0] instanceof ArtifactDescriptor) { + HashMap<String, String> map = new HashMap<String, String>(); + map.put(P_STATS_MARKER, feature.getFeatureIdentifier()); + ((ArtifactDescriptor) descriptors[0]).addProperties(map); + } + } + } + } + } + SiteBundle[] bundles = site.getStatsBundles(); + if (bundles != null) { + for (SiteBundle bundle : bundles) { + if (monitor.isCanceled()) + return Status.CANCEL_STATUS; + Collection<IInstallableUnit> ius = getBundleIU(bundle, publisherInfo, results); + if (ius != null) { + for (IInstallableUnit iu : ius) { + IArtifactKey key = BundlesAction.createBundleArtifactKey(iu.getId(), iu.getVersion().toString()); + IArtifactDescriptor[] descriptors = publisherInfo.getArtifactRepository().getArtifactDescriptors(key); + if (descriptors.length > 0 && descriptors[0] instanceof ArtifactDescriptor) { + HashMap<String, String> map = new HashMap<String, String>(); + map.put(P_STATS_MARKER, iu.getId()); + ((ArtifactDescriptor) descriptors[0]).addProperties(map); + } + } + } + } + } + // Process all ius that should be marked for download stat tracking + return Status.OK_STATUS; + } private IStatus generateCategories(IPublisherInfo publisherInfo, IPublisherResult results, IProgressMonitor monitor) { @@ -408,6 +462,13 @@ public class SiteXMLAction extends AbstractPublisherAction { publisherInfo.getMetadataRepository().addReferences(toAdd); } + // publish download stats URL from category file + String statsURI = site.getStatsURI(); + if (statsURI != null && statsURI.length() > 0) { + if (publisherInfo.getArtifactRepository() != null) + publisherInfo.getArtifactRepository().setProperty(P_STATS_URI, statsURI); + } + File siteFile = URIUtil.toFile(updateSite.getLocation()); if (siteFile != null && siteFile.exists()) { File siteParent = siteFile.getParentFile(); |