Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: 43c87de35ece6f507a6c7a5a132dd11c36248446 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                                                                
                                                                        


                                                                               

                
                                            
                              
                                     
                                           



                                                                                

                                   
                   
                           

                                                              
                                                            

                                                      
                                                                                  

                                                                 
                                          
                                                  

                                                     
                                                              
                                                                      
                                                                      
                                                                         
                                                                 

                                                               





                                                                                          
                                                                          

                                                                                    
                                                                                                          
                                        
                                             
                                                         
                               
                                                
                                               
 







                                                                                                             
                                         
                                                           

         

                                                                                                           
                                            




                                                                                                    
                                             
                                                           

         



                                                                
                                   

                                            



                                                                                                                      
                                                      


                                                        
                 
                                                                                                                  

                                         
                                                                                                                                                                                             
                                                        
                                                                                                                     




                                                                
                                                      







                                                                                                                              
                                                                                         


                                                                 
                                                               






                                                                                                                                                                       
                                                                                                                             
                                                                                                                             
                                                                                                      






                                                                                                                 
                                                                
                                                              
                                                              






                                                                                                                                                 
                                                                                                                             
                                                                                                                             
                                                                                                      






                                                                                                                 





                                                                                                                                                                            

                                        

         
                                                                                                                              
                                                                                           
                                                                                                                       
                                                                           

                                                            

                                                                                                         
                                         
                                                                                         


                                                                                                           
                                                                  

                                                                                                    
                                                                        
                                                                                     
                                 
                                                          

                         














                                                                                                                    
                                                                        





                                                                                     

                                                                                
                                        

         
                                                                                                                                                               
                                                                                                        




                                                      
                                                                                                  
                                        
                                         






                                                                                                           
                                                                        
                                                                                     
                                 
                                                          



                         
                                                                                                      
                                                                              









                                                                                 
                                                                       










                                                                                           






                                                                                                                            
                                                       

                                                      
                                                                         
                                                                    
                                                                  
                                                                          
                                                              
                                                                               
                                  
                                                       





                                                                                                      
                                                       

         

                                                                                                                              
                                                                                                                                        
                                                                                            
                                                                   

                                                                                                                                             
                                                           
                                                            


                                         
                                                                                                  



                                                                                 
                                                                                            
                                                                                                                                    
                                                       
                                
                                                                                                            
                         
                 
 




                                                                                                      
 
                                           
                                                               


                            

































                                                                                                                                             












                                                                                                      

                                                                                                                                                     











                                                                                                                                                         




                                                                                         
                                                                                                                  
                                                                                   





                                                      



                                                                                 

                                                                                 
                                                             

                                                                      














                                                                                                                
                                                                                  









                                                                                 
                                                                       















                                                                                                         
                                                                             
                                                      




                                                                                                                                     
                                                                                                                 
                                                                                                                

                                                                                                                         



                                                                       
                                              
                                                                                                           














                                                                                                                                                    
 


                                                                             
                                                                                                     


                                                                                   






                                                                                                         


                                                                         
                                                                         
                                                       
                                                                                                          

                                                                                                                                                          
                                                                                                          
                                                                                                                                                          

                         


           
                                                                 
                                                                                           

                                                         
                                                                                                                               
                                                                           


                                                                                         
                                                                                                        









                                                                                                                    
                                                                                                                          
                                                     
                                                                                     
                                               
                                                                                                      
                                 
                                                                                            



                                                                                                                  

                                                  




















                                                                                                             


                                         


                                                                         
                                                                                 


                                                                                    
                                                        














                                                                                                                           





                                                                 

                                                                                                                               
                                                  
                                                                                                       
           

                                                                                                                                             
                                                               















                                                                                                                               

                                                                                                  
                                                                        
                                      
                                            
                                                                                                                                                 

                                                                 
                                                                                                                        

                                                                              
                                                                                                                                    





                                                                                                                                                                
 

                                                                                                        

                                                                                              
                                                                                                     
                                                         
                                                                                                            
                                                                                                                                                                         
                 
                                                                                                                     

                                                      
                                                                                        
                                                                                                             
 
                                                                                             
                                            




                                                                                                            




                                                                                                                        
                                                                                                                        

                                                      
                                                                                                     


                                                                  
           
                                                                                         


                                                             


                                                                                            
                                            
                 



                                                                                                                      









                                                                                                                 
 
/*******************************************************************************
 * Copyright (c) 2008, 2018 Code 9 and others. All rights reserved. This
 * program and the accompanying materials are made available under the terms of
 * the Eclipse Public License v1.0 which accompanies this distribution, and is
 * available at http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   Code 9 - initial API and implementation
 *   IBM - ongoing development
 *   Sonatype, Inc. - transport split
 *   Red Hat Inc. - 383795 (bundle element)
 ******************************************************************************/
package org.eclipse.equinox.internal.p2.updatesite;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.Map.Entry;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.repository.Transport;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
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.*;
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.IArtifactRepository;
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;

/**
 * Action which processes a site.xml and generates categories.  The categorization process
 * relies on IUs for the various features to have already been generated.
 */
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;
	private HashSet<SiteCategory> defaultCategorySet;
	protected URI location;
	private String categoryQualifier = null;
	private Version categoryVersion = null;

	/**
	 * Creates a SiteXMLAction from a Location (URI) with an optional qualifier to use for category names
	 * @param location The location of the update site
	 * @param categoryQualifier The qualifier to prepend to categories. This qualifier is used
	 * to ensure that the category IDs are unique between update sites. If <b>null</b> a default
	 * qualifier will be generated
	 */
	public SiteXMLAction(URI location, String categoryQualifier) {
		this.location = location;
		this.categoryQualifier = categoryQualifier;
	}

	/**
	 * Creates a SiteXMLAction from an Update site with an optional qualifier to use for category names
	 * @param updateSite The update site
	 * @param categoryQualifier The qualifier to prepend to categories. This qualifier is used
	 * to ensure that the category IDs are unique between update sites. If <b>null</b> a default
	 * qualifier will be generated
	 */
	public SiteXMLAction(UpdateSite updateSite, String categoryQualifier) {
		this.updateSite = updateSite;
		this.categoryQualifier = categoryQualifier;
	}

	public void setCategoryVersion(String version) {
		categoryVersion = Version.parseVersion(version);
	}

	private void initialize() {
		if (defaultCategory != null)
			return;
		defaultCategory = new SiteCategory();
		defaultCategory.setDescription("Default category for otherwise uncategorized features"); //$NON-NLS-1$
		defaultCategory.setLabel("Uncategorized"); //$NON-NLS-1$
		defaultCategory.setName("Default"); //$NON-NLS-1$
		defaultCategorySet = new HashSet<>(1);
		defaultCategorySet.add(defaultCategory);
	}

	@Override
	public IStatus perform(IPublisherInfo publisherInfo, IPublisherResult results, IProgressMonitor monitor) {
		if (updateSite == null) {
			try {
				updateSite = UpdateSite.load(location, (Transport) publisherInfo.getMetadataRepository().getProvisioningAgent().getService(Transport.SERVICE_NAME), monitor);
			} catch (ProvisionException e) {
				return new Status(IStatus.ERROR, Activator.ID, Messages.Error_generating_siteXML, e);
			} catch (OperationCanceledException e) {
				return Status.CANCEL_STATUS;
			}
		}
		initialize();
		initializeRepoFromSite(publisherInfo);
		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) {
		IArtifactRepository artifactRepo = publisherInfo.getArtifactRepository();
		SiteModel site = updateSite.getSite();
		// process all features listed and mark artifacts
		SiteFeature[] features = site.getStatsFeatures();
		if (features != null && artifactRepo != 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 = artifactRepo.getArtifactDescriptors(key);
						if (descriptors.length > 0 && descriptors[0] instanceof ArtifactDescriptor) {
							HashMap<String, String> map = new HashMap<>();
							map.put(P_STATS_MARKER, feature.getFeatureIdentifier());
							((ArtifactDescriptor) descriptors[0]).addProperties(map);
						}
					}
				}
			}
		}
		// process all bundles listed and mark artifacts
		SiteBundle[] bundles = site.getStatsBundles();
		if (bundles != null && artifactRepo != 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 = artifactRepo.getArtifactDescriptors(key);
						if (descriptors.length > 0 && descriptors[0] instanceof ArtifactDescriptor) {
							HashMap<String, String> map = new HashMap<>();
							map.put(P_STATS_MARKER, iu.getId());
							((ArtifactDescriptor) descriptors[0]).addProperties(map);
						}
					}
				}
			}
		}
		// If there was no artifact repository available and stats were to be tracked, issue
		// a warning.
		boolean markingBundles = bundles != null && bundles.length > 0;
		boolean markingFeatures = features != null && features.length > 0;
		if (artifactRepo == null && (markingBundles || markingFeatures))
			return new Status(IStatus.WARNING, Activator.ID, "Artifact repository was not specified so stats properties could not be published."); //$NON-NLS-1$
		return Status.OK_STATUS;

	}

	private IStatus generateCategories(IPublisherInfo publisherInfo, IPublisherResult results, IProgressMonitor monitor) {
		Map<SiteCategory, Set<IInstallableUnit>> categoriesToIUs = new HashMap<>();
		Map<SiteFeature, Set<SiteCategory>> featuresToCategories = getFeatureToCategoryMappings(publisherInfo);
		for (SiteFeature feature : featuresToCategories.keySet()) {
			if (monitor.isCanceled())
				return Status.CANCEL_STATUS;
			Collection<IInstallableUnit> ius = getFeatureIU(feature, publisherInfo, results);
			if (ius == null)
				continue;
			Set<SiteCategory> categories = featuresToCategories.get(feature);
			// if there are no categories for this feature then add it to the default category.
			if (categories == null || categories.isEmpty())
				categories = defaultCategorySet;
			for (SiteCategory category : categories) {
				Set<IInstallableUnit> iusInCategory = categoriesToIUs.get(category);
				if (iusInCategory == null) {
					iusInCategory = new HashSet<>();
					categoriesToIUs.put(category, iusInCategory);
				}
				iusInCategory.addAll(ius);
			}
		}
		// Bundles -- bug 378338
		Map<SiteBundle, Set<SiteCategory>> bundlesToCategories = getBundleToCategoryMappings(publisherInfo);
		for (SiteBundle bundle : bundlesToCategories.keySet()) {
			if (monitor.isCanceled())
				return Status.CANCEL_STATUS;
			Collection<IInstallableUnit> ius = getBundleIU(bundle, publisherInfo, results);
			if (ius == null)
				continue;
			Set<SiteCategory> categories = bundlesToCategories.get(bundle);
			// if there are no categories for this feature then add it to the default category.
			if (categories == null || categories.isEmpty())
				categories = defaultCategorySet;
			for (SiteCategory category : categories) {
				Set<IInstallableUnit> iusInCategory = categoriesToIUs.get(category);
				if (iusInCategory == null) {
					iusInCategory = new HashSet<>();
					categoriesToIUs.put(category, iusInCategory);
				}
				iusInCategory.addAll(ius);
			}
		}

		addSiteIUsToCategories(categoriesToIUs, publisherInfo, results);
		generateCategoryIUs(categoriesToIUs, results);
		return Status.OK_STATUS;
	}

	private void addSiteIUsToCategories(Map<SiteCategory, Set<IInstallableUnit>> categoriesToIUs, IPublisherInfo publisherInfo, IPublisherResult results) {
		Map<SiteIU, Set<SiteCategory>> iusToCategories = getIUToCategoryMappings(publisherInfo);
		SiteModel site = updateSite.getSite();
		if (site == null)
			return;
		SiteIU[] siteIUs = site.getIUs();
		for (SiteIU siteIU : siteIUs) {
			Collection<IInstallableUnit> ius = getIUs(siteIU, publisherInfo, results);
			if (ius == null)
				continue;
			Set<SiteCategory> categories = iusToCategories.get(siteIU);
			// if there are no categories for this feature then add it to the default category.
			if (categories == null || categories.isEmpty())
				categories = defaultCategorySet;
			for (SiteCategory category : categories) {
				Set<IInstallableUnit> iusInCategory = categoriesToIUs.get(category);
				if (iusInCategory == null) {
					iusInCategory = new HashSet<>();
					categoriesToIUs.put(category, iusInCategory);
				}
				iusInCategory.addAll(ius);
			}
		}
	}

	private Map<SiteIU, Set<SiteCategory>> getIUToCategoryMappings(IPublisherInfo publisherInfo) {
		HashMap<SiteIU, Set<SiteCategory>> mappings = new HashMap<>();
		if (updateSite == null)
			return mappings;
		SiteModel site = updateSite.getSite();
		if (site == null)
			return mappings;

		SiteIU[] ius = site.getIUs();
		for (int i = 0; i < ius.length; i++) {
			//add a mapping for each category this feature belongs to
			String[] categoryNames = ius[i].getCategoryNames();
			Set<SiteCategory> categories = new HashSet<>();
			mappings.put(ius[i], categories);
			for (int j = 0; j < categoryNames.length; j++) {
				SiteCategory category = site.getCategory(categoryNames[j]);
				if (category != null)
					categories.add(category);
			}
		}
		return mappings;

	}

	private Collection<IInstallableUnit> getIUs(SiteIU siteIU, IPublisherInfo publisherInfo, IPublisherResult results) {
		String id = siteIU.getID();
		String range = siteIU.getRange();
		String type = siteIU.getQueryType();
		String expression = siteIU.getQueryExpression();
		Object[] params = siteIU.getQueryParams();
		if (id == null && (type == null || expression == null))
			return Collections.emptyList();
		IQuery<IInstallableUnit> query = null;
		if (id != null) {
			VersionRange vRange = VersionRange.create(range);
			query = QueryUtil.createIUQuery(id, vRange);
		} else if (type.equals("context")) { //$NON-NLS-1$
			query = QueryUtil.createQuery(expression, params);
		} else if (type.equals("match")) //$NON-NLS-1$
			query = QueryUtil.createMatchQuery(expression, params);
		if (query == null)
			return Collections.emptyList();
		IQueryResult<IInstallableUnit> queryResult = results.query(query, null);
		if (queryResult.isEmpty())
			queryResult = publisherInfo.getMetadataRepository().query(query, null);
		if (queryResult.isEmpty() && publisherInfo.getContextMetadataRepository() != null)
			queryResult = publisherInfo.getContextMetadataRepository().query(query, null);

		return queryResult.toUnmodifiableSet();
	}

	private static final IExpression qualifierMatchExpr = ExpressionUtil.parse("id == $0 && version ~= $1"); //$NON-NLS-1$

	private Collection<IInstallableUnit> getFeatureIU(SiteFeature feature, IPublisherInfo publisherInfo, IPublisherResult results) {
		String id = feature.getFeatureIdentifier() + ".feature.group"; //$NON-NLS-1$
		String versionString = feature.getFeatureVersion();
		Version version = versionString != null && versionString.length() > 0 ? Version.create(versionString) : Version.emptyVersion;
		IQuery<IInstallableUnit> query = null;
		if (version.equals(Version.emptyVersion)) {
			query = QueryUtil.createIUQuery(id);
		} else {
			String qualifier;
			try {
				qualifier = PublisherHelper.toOSGiVersion(version).getQualifier();
			} catch (UnsupportedOperationException e) {
				qualifier = null;
			}
			if (qualifier != null && qualifier.endsWith(QUALIFIER)) {
				VersionRange range = createVersionRange(version.toString());
				IQuery<IInstallableUnit> qualifierQuery = QueryUtil.createMatchQuery(qualifierMatchExpr, id, range);
				query = qualifierQuery;
			} else {
				query = QueryUtil.createLimitQuery(QueryUtil.createIUQuery(id, version), 1);
			}
		}

		IQueryResult<IInstallableUnit> queryResult = results.query(query, null);
		if (queryResult.isEmpty())
			queryResult = publisherInfo.getMetadataRepository().query(query, null);
		if (queryResult.isEmpty() && publisherInfo.getContextMetadataRepository() != null)
			queryResult = publisherInfo.getContextMetadataRepository().query(query, null);

		if (!queryResult.isEmpty())
			return queryResult.toUnmodifiableSet();
		return null;
	}

	private Collection<IInstallableUnit> getBundleIU(SiteBundle bundle, IPublisherInfo publisherInfo, IPublisherResult results) {
		String id = bundle.getBundleIdentifier();
		String versionString = bundle.getBundleVersion();
		Version version = versionString != null && versionString.length() > 0 ? Version.create(versionString) : Version.emptyVersion;
		IQuery<IInstallableUnit> query = null;
		if (version.equals(Version.emptyVersion)) {
			query = QueryUtil.createIUQuery(id);
		} else {
			String qualifier;
			try {
				qualifier = PublisherHelper.toOSGiVersion(version).getQualifier();
			} catch (UnsupportedOperationException e) {
				qualifier = null;
			}
			if (qualifier != null && qualifier.endsWith(QUALIFIER)) {
				VersionRange range = createVersionRange(version.toString());
				IQuery<IInstallableUnit> qualifierQuery = QueryUtil.createMatchQuery(qualifierMatchExpr, id, range);
				query = qualifierQuery;
			} else {
				query = QueryUtil.createLimitQuery(QueryUtil.createIUQuery(id, version), 1);
			}
		}

		IQueryResult<IInstallableUnit> queryResult = results.query(query, null);
		if (queryResult.isEmpty())
			queryResult = publisherInfo.getMetadataRepository().query(query, null);
		if (queryResult.isEmpty() && publisherInfo.getContextMetadataRepository() != null)
			queryResult = publisherInfo.getContextMetadataRepository().query(query, null);

		if (!queryResult.isEmpty())
			return queryResult.toUnmodifiableSet();
		return null;
	}

	protected VersionRange createVersionRange(String versionId) {
		VersionRange range = null;
		if (versionId == null || "0.0.0".equals(versionId)) //$NON-NLS-1$
			range = VersionRange.emptyRange;
		else {
			int qualifierIdx = versionId.indexOf(QUALIFIER);
			if (qualifierIdx != -1) {
				String newVersion = versionId.substring(0, qualifierIdx);
				if (newVersion.endsWith(".")) //$NON-NLS-1$
					newVersion = newVersion.substring(0, newVersion.length() - 1);

				Version lower = Version.parseVersion(newVersion);
				Version upper = null;
				String newQualifier = VersionSuffixGenerator.incrementQualifier(PublisherHelper.toOSGiVersion(lower).getQualifier());
				org.osgi.framework.Version osgiVersion = PublisherHelper.toOSGiVersion(lower);
				if (newQualifier == null)
					upper = Version.createOSGi(osgiVersion.getMajor(), osgiVersion.getMinor(), osgiVersion.getMicro() + 1);
				else
					upper = Version.createOSGi(osgiVersion.getMajor(), osgiVersion.getMinor(), osgiVersion.getMicro(), newQualifier);
				range = new VersionRange(lower, true, upper, false);
			} else {
				range = new VersionRange(Version.parseVersion(versionId), true, Version.parseVersion(versionId), true);
			}
		}
		return range;
	}

	/**
	 * Computes the mapping of features to categories as defined in the site.xml,
	 * if available. Returns an empty map if there is not site.xml, or no categories.
	 * @return A map of SiteFeature -> Set<SiteCategory>.
	 */
	protected Map<SiteFeature, Set<SiteCategory>> getFeatureToCategoryMappings(IPublisherInfo publisherInfo) {
		HashMap<SiteFeature, Set<SiteCategory>> mappings = new HashMap<>();
		if (updateSite == null)
			return mappings;
		SiteModel site = updateSite.getSite();
		if (site == null)
			return mappings;

		SiteFeature[] features = site.getFeatures();
		for (int i = 0; i < features.length; i++) {
			//add a mapping for each category this feature belongs to
			String[] categoryNames = features[i].getCategoryNames();
			Set<SiteCategory> categories = mappings.get(features[i]);
			if (categories == null) {
				categories = new HashSet<>();
				mappings.put(features[i], categories);
			}
			for (int j = 0; j < categoryNames.length; j++) {
				SiteCategory category = site.getCategory(categoryNames[j]);
				if (category != null)
					categories.add(category);
			}
		}
		return mappings;
	}

	/**
	 * Computes the mapping of bundles to categories as defined in the site.xml,
	 * if available. Returns an empty map if there is not site.xml, or no categories.
	 * @return A map of SiteBundle -> Set<SiteCategory>.
	 */
	protected Map<SiteBundle, Set<SiteCategory>> getBundleToCategoryMappings(IPublisherInfo publisherInfo) {
		HashMap<SiteBundle, Set<SiteCategory>> mappings = new HashMap<>();
		if (updateSite == null)
			return mappings;
		SiteModel site = updateSite.getSite();
		if (site == null)
			return mappings;

		SiteBundle[] bundles = site.getBundles();
		for (int i = 0; i < bundles.length; i++) {
			//add a mapping for each category this feature belongs to
			String[] categoryNames = bundles[i].getCategoryNames();
			Set<SiteCategory> categories = new HashSet<>();
			mappings.put(bundles[i], categories);
			for (int j = 0; j < categoryNames.length; j++) {
				SiteCategory category = site.getCategory(categoryNames[j]);
				if (category != null)
					categories.add(category);
			}
		}
		return mappings;
	}

	/**
	 * Initializes new p2 repository attributes such as mirror info, associate sites, localization...
	 * @param publisherInfo configuration for output repository
	 */
	private void initializeRepoFromSite(IPublisherInfo publisherInfo) {
		SiteModel site = updateSite.getSite();
		//copy mirror information from update site to p2 repositories
		String mirrors = site.getMirrorsURI();
		if (mirrors != null) {
			//remove site.xml file reference
			int index = mirrors.indexOf("site.xml"); //$NON-NLS-1$
			if (index != -1)
				mirrors = mirrors.substring(0, index) + mirrors.substring(index + "site.xml".length()); //$NON-NLS-1$
			publisherInfo.getMetadataRepository().setProperty(IRepository.PROP_MIRRORS_URL, mirrors);
			// there does not really need to be an artifact repo but if there is, setup its mirrors.
			if (publisherInfo.getArtifactRepository() != null)
				publisherInfo.getArtifactRepository().setProperty(IRepository.PROP_MIRRORS_URL, mirrors);
		}

		//publish associate sites as repository references
		URLEntry[] associatedSites = site.getAssociatedSites();
		if (associatedSites != null) {
			ArrayList<IRepositoryReference> refs = new ArrayList<>(associatedSites.length * 2);
			for (int i = 0; i < associatedSites.length; i++) {
				URLEntry associatedSite = associatedSites[i];
				String siteLocation = associatedSite.getURL();
				try {
					URI associateLocation = new URI(siteLocation);
					String label = associatedSite.getAnnotation();
					refs.add(new RepositoryReference(associateLocation, label, IRepository.TYPE_METADATA, IRepository.ENABLED));
					refs.add(new RepositoryReference(associateLocation, label, IRepository.TYPE_ARTIFACT, IRepository.ENABLED));
				} catch (URISyntaxException e) {
					String message = "Invalid site reference: " + siteLocation; //$NON-NLS-1$
					LogHelper.log(new Status(IStatus.ERROR, Activator.ID, message));
				}
			}
			publisherInfo.getMetadataRepository().addReferences(refs);
		}

		//publish repository references from category file
		IRepositoryReference[] refs = site.getRepositoryReferences();
		if (refs != null) {
			ArrayList<IRepositoryReference> toAdd = new ArrayList<>(Arrays.asList(refs));
			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();
			List<String> messageKeys = site.getMessageKeys();
			if (siteParent.isDirectory()) {
				String[] keyStrings = messageKeys.toArray(new String[messageKeys.size()]);
				site.setLocalizations(LocalizationHelper.getDirPropertyLocalizations(siteParent, "site", null, keyStrings)); //$NON-NLS-1$
			} else if (siteFile.getName().endsWith(".jar")) { //$NON-NLS-1$
				String[] keyStrings = messageKeys.toArray(new String[messageKeys.size()]);
				site.setLocalizations(LocalizationHelper.getJarPropertyLocalizations(siteParent, "site", null, keyStrings)); //$NON-NLS-1$
			}
		}
	}

	/**
	 * Generates IUs corresponding to update site categories.
	 * @param categoriesToIUs Map of SiteCategory ->Set (Feature IUs in that category).
	 * @param result The generator result being built
	 */
	protected void generateCategoryIUs(Map<SiteCategory, Set<IInstallableUnit>> categoriesToIUs, IPublisherResult result) {
		Map<String, SiteCategory> nameToCategory = new HashMap<>();
		for (SiteCategory category : this.updateSite.getSite().getCategories()) {
			nameToCategory.put(category.getName(), category);
		}
		final Map<SiteCategory, Set<SiteCategory>> categoryToNestedCategories = new HashMap<>();
		for (SiteCategory category : this.updateSite.getSite().getCategories()) {
			for (String parentCategoryName : category.getCategoryNames()) {
				SiteCategory parentCategory = nameToCategory.get(parentCategoryName);
				if (categoryToNestedCategories.get(parentCategory) == null) {
					categoryToNestedCategories.put(parentCategory, new HashSet<SiteCategory>());
				}
				categoryToNestedCategories.get(parentCategory).add(category);
			}
		}

		List<SiteCategory> categories = new ArrayList<>(Arrays.asList(this.updateSite.getSite().getCategories()));
		categories.add(this.defaultCategory);
		// sort category so they are processed in reverse order of dependency
		// (Nested categories go first)
		Comparator<SiteCategory> isNestedCategoryComparator = new Comparator<SiteCategory>() {
			@Override
			public int compare(SiteCategory category1, SiteCategory category2) {
				Set<SiteCategory> childrenOfCategory1 = categoryToNestedCategories.get(category1);
				Set<SiteCategory> childrenOfCategory2 = categoryToNestedCategories.get(category2);
				if (childrenOfCategory1 != null && childrenOfCategory1.contains(category2)) {
					// category2 nested in category1 => category2 < category1
					return +1;
				}
				if (childrenOfCategory2 != null && childrenOfCategory2.contains(category1)) {
					// category1 nested in category2 => category1 < category2
					return -1;
				}
				// Then recurse in childrenCategories for transitivity
				if (childrenOfCategory1 != null) {
					for (SiteCategory childOfCategory1 : childrenOfCategory1) {
						int res = this.compare(childOfCategory1, category2);
						if (res != 0) {
							return res;
						}
					}
				}
				if (childrenOfCategory2 != null) {
					for (SiteCategory childOfCategory2 : childrenOfCategory2) {
						int res = this.compare(category1, childOfCategory2);
						if (res != 0) {
							return res;
						}
					}
				}
				return 0;
			}
		};
		Collections.sort(categories, isNestedCategoryComparator);

		// Then create categories in the right order
		Map<String, IInstallableUnit> nameToCategoryIU = new HashMap<>();
		for (SiteCategory category : categories) {
			Set<IInstallableUnit> units = categoriesToIUs.get(category);
			if (units == null) {
				units = new HashSet<>();
			}
			Set<SiteCategory> nestedCategories = categoryToNestedCategories.get(category);
			if (nestedCategories != null) {
				for (SiteCategory nestedCategory : nestedCategories) {
					IInstallableUnit nestedCategoryIU = nameToCategoryIU.get(nestedCategory.getName());
					if (nestedCategoryIU != null) {
						units.add(nestedCategoryIU);
					}
				}
			}
			if (!units.isEmpty()) {
				IInstallableUnit categoryIU = createCategoryIU(category, units);
				result.addIU(categoryIU, IPublisherResult.NON_ROOT);
				nameToCategoryIU.put(category.getName(), categoryIU);
			}
		}
	}

	/**
	 * Creates an IU corresponding to an update site category
	 * @param category The category descriptor
	 * @param childrenIUs The IUs of the children that belong to the category (can be bundle, feature or nested categories)
	 * @param nestedCategory A nested category (optional)
	 * @return an IU representing the category
	 * @deprecated use {@link IInstallableUnit}{@link #createCategoryIU(SiteCategory, Set)} instead
	 */
	@Deprecated
	public IInstallableUnit createCategoryIU(SiteCategory category, Set<IInstallableUnit> childrenIUs, IInstallableUnit nestedCategory) {
		Set<IInstallableUnit> allIUs = new HashSet<>();
		if (childrenIUs != null) {
			allIUs.addAll(childrenIUs);
		}
		if (nestedCategory != null) {
			allIUs.add(nestedCategory);
		}
		return createCategoryIU(category, allIUs);
	}

	/**
	 * Creates an IU corresponding to an update site category
	 * @param category The category descriptor
	 * @param childrenIUs The IUs of the children that belong to the category (can be bundle, feature or nested categories)
	 * @return an IU representing the category
	 */
	public IInstallableUnit createCategoryIU(SiteCategory category, Set<IInstallableUnit> childrenIUs) {
		InstallableUnitDescription cat = new MetadataFactory.InstallableUnitDescription();
		cat.setSingleton(true);
		String categoryId = buildCategoryId(category.getName());
		cat.setId(categoryId);
		if (categoryVersion == null)
			cat.setVersion(Version.createOSGi(1, 0, 0, versionSuffixGenerator.generateSuffix(childrenIUs, Collections.emptyList())));
		else {
			if (categoryVersion.isOSGiCompatible()) {
				org.osgi.framework.Version osgiVersion = PublisherHelper.toOSGiVersion(categoryVersion);
				String qualifier = osgiVersion.getQualifier();
				if (qualifier.endsWith(QUALIFIER)) {
					String suffix = versionSuffixGenerator.generateSuffix(childrenIUs, Collections.emptyList());
					qualifier = qualifier.substring(0, qualifier.length() - 9) + suffix;
					categoryVersion = Version.createOSGi(osgiVersion.getMajor(), osgiVersion.getMinor(), osgiVersion.getMicro(), qualifier);
				}
			}
			cat.setVersion(categoryVersion);
		}

		String label = category.getLabel();
		cat.setProperty(IInstallableUnit.PROP_NAME, label != null ? label : category.getName());
		cat.setProperty(IInstallableUnit.PROP_DESCRIPTION, category.getDescription());

		ArrayList<IRequirement> reqsConfigurationUnits = new ArrayList<>(childrenIUs.size());
		for (IInstallableUnit iu : childrenIUs) {
			VersionRange range = new VersionRange(iu.getVersion(), true, iu.getVersion(), true);
			reqsConfigurationUnits.add(MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, iu.getId(), range, iu.getFilter(), false, false));
		}
		cat.setRequirements(reqsConfigurationUnits.toArray(new IRequirement[reqsConfigurationUnits.size()]));

		// Create set of provided capabilities
		ArrayList<IProvidedCapability> providedCapabilities = new ArrayList<>();
		providedCapabilities.add(PublisherHelper.createSelfCapability(categoryId, cat.getVersion()));

		Map<Locale, Map<String, String>> localizations = category.getLocalizations();
		if (localizations != null) {
			for (Entry<Locale, Map<String, String>> locEntry : localizations.entrySet()) {
				Locale locale = locEntry.getKey();
				Map<String, String> translatedStrings = locEntry.getValue();
				for (Entry<String, String> e : translatedStrings.entrySet()) {
					cat.setProperty(locale.toString() + '.' + e.getKey(), e.getValue());
				}
				providedCapabilities.add(PublisherHelper.makeTranslationCapability(categoryId, locale));
			}
		}

		cat.setCapabilities(providedCapabilities.toArray(new IProvidedCapability[providedCapabilities.size()]));

		cat.setArtifacts(new IArtifactKey[0]);
		cat.setProperty(InstallableUnitDescription.PROP_TYPE_CATEGORY, "true"); //$NON-NLS-1$
		return MetadataFactory.createInstallableUnit(cat);
	}

	/**
	 * Creates a qualified category id. This action's qualifier is used if one exists
	 * or an existing update site's location is used.
	 */
	private String buildCategoryId(String categoryName) {
		if (categoryQualifier != null) {
			if (categoryQualifier.length() > 0)
				return categoryQualifier + "." + categoryName; //$NON-NLS-1$
			return categoryName;
		}
		if (updateSite != null)
			return URIUtil.toUnencodedString(updateSite.getLocation()) + "." + categoryName; //$NON-NLS-1$
		return categoryName;
	}

	protected Transport getTransport(IPublisherInfo info) {
		@SuppressWarnings("rawtypes")
		IRepository repo = info.getMetadataRepository();
		if (repo == null)
			repo = info.getArtifactRepository();
		if (repo == null)
			throw new IllegalStateException("The transport service can not be found."); //$NON-NLS-1$
		return (Transport) repo.getProvisioningAgent().getService(Transport.SERVICE_NAME);
	}
}

Back to the top