blob: ecf621cf7e8dd5ec1c9e5371e3467ab6e5e4d2ad [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2016 IBM Corporation 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:
* IBM Corporation - Initial API and implementation
*******************************************************************************/
package org.eclipse.wst.server.discovery.internal.model;
import java.net.URI;
import java.util.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.equinox.internal.p2.updatesite.metadata.UpdateSiteMetadataRepositoryFactory;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IRequirement;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
import org.eclipse.equinox.p2.query.*;
import org.eclipse.equinox.p2.repository.IRepositoryManager;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.wst.server.discovery.internal.ExtensionUtility;
import org.eclipse.wst.server.discovery.internal.Trace;
import org.osgi.framework.BundleContext;
/*
* From Kosta:
* feature version (optional)
* alternate name (optional) - defaults to feature name
*/
public class ExtensionUpdateSite {
private static final List<String> EMPTY_LIST = new ArrayList<String>(0);
public static final String SERVER_ADAPTER_ID = "org.eclipse.wst.server.core.serverAdapter"; //$NON-NLS-1$
private String url;
private String featureId;
private List<String> categories;
public ExtensionUpdateSite() {
// do nothing
}
public ExtensionUpdateSite(String url, String featureId, List<String> categories) {
this.url = url;
this.featureId = featureId;
this.categories = categories;
}
public String getUrl() {
return url;
}
public String getFeatureId() {
return featureId;
}
public List<String> getCategories() {
if (categories == null)
return EMPTY_LIST;
return categories;
}
public List<IServerExtension> getExtensions(IProgressMonitor monitor) throws CoreException , ProvisionException{
URI url2 = null;
IMetadataRepositoryManager manager = null;
IProvisioningAgent agent = null;
List<IServerExtension> list = new ArrayList<IServerExtension>();
URI[] existingSites = null;
try {
/*
* To discovery the server adapter, there are three methods:
* 1. Looking at the site.xml (if it exists). This is the legacy method
* 2. Looking for the org.eclipse.wst.server.core.serverAdapter property in a p2
* update site (that may not have a site.xml). The property is necessary to identify
* the InstallableUnit as a server type. Otherwise, all the InstallableUnits will show
* up regardless of whether it is a server or not
* 3. If the user created the p2 update site using a category.xml file (migrating old site.xml
* to use category.xml)
*/
BundleContext bd = org.eclipse.wst.server.discovery.internal.Activator.getDefault().getBundle().getBundleContext();
agent = ExtensionUtility.getAgent(bd);
url2 = new URI(url);
// Method 1: Looking at the site.xml
UpdateSiteMetadataRepositoryFactory mrf = new UpdateSiteMetadataRepositoryFactory();
mrf.setAgent(ExtensionUtility.getAgent(bd));
manager = (IMetadataRepositoryManager) agent.getService(IMetadataRepositoryManager.SERVICE_NAME);
// Sites already existing for both enabled and disabled
URI[] existingSitesAll = manager.getKnownRepositories(IMetadataRepositoryManager.REPOSITORIES_ALL);
URI[] existingSitesDisabled = manager.getKnownRepositories(IMetadataRepositoryManager.REPOSITORIES_DISABLED);
int existingSitesAllLen = existingSitesAll == null ? 0 : existingSitesAll.length;
int existingSitesDisabledLen = existingSitesDisabled == null ? 0 : existingSitesDisabled.length;
existingSites = new URI[existingSitesAllLen + existingSitesDisabledLen];
if (existingSitesAllLen > 0) {
System.arraycopy(existingSitesAll, 0, existingSites, 0, existingSitesAllLen);
}
if (existingSitesDisabledLen > 0) {
System.arraycopy(existingSitesDisabled, 0, existingSites, existingSitesAllLen, existingSitesDisabledLen);
}
// If the site.xml does not exist, the load will throw a org.eclipse.equinox.p2.core.ProvisionException
try {
IMetadataRepository repo = mrf.load(url2, IRepositoryManager.REPOSITORIES_ALL, monitor);
IQuery<IInstallableUnit> query = QueryUtil.createMatchQuery("id ~=/*org.eclipse.wst.server.core.serverAdapter/"); //$NON-NLS-1$
list = getInstallableUnits(repo,query,url2,monitor);
}
catch (ProvisionException pe){
Trace.trace(Trace.WARNING, "Error getting update site information", pe); //$NON-NLS-1$
}
// Call Method 2 if there are no results from Method 1 (e.g. if the site.xml exists without
// specifying any server adapters there or no site.xml exists)
if (list.isEmpty()){
manager.addRepository(url2);
// Need to query for all IUs
IQuery<IInstallableUnit> query = QueryUtil.createIUAnyQuery();
IMetadataRepository repo = manager.loadRepository(url2, monitor);
List<IServerExtension> list2 = getInstallableUnits(repo,query,url2,monitor);
int size = list2.size();
for (int i=0;i<size;i++){
Extension e = (Extension)list2.get(i);
IInstallableUnit[] iuArr = e.getIUs();
if(iuArr != null && iuArr.length > 0){
if (iuArr[0] != null){
if (iuArr[0].getProperty(SERVER_ADAPTER_ID) != null){
list.add(e);
}
}
}
}
}
// Call Method 3 if no results from Method 2. Creating the p2 update site using the category.xml will generate
// a provider property with org.eclipse.wst.server.core.serverAdapter
if (list.isEmpty()){
manager = (IMetadataRepositoryManager) agent.getService(IMetadataRepositoryManager.SERVICE_NAME);
manager.addRepository(url2);
IQuery<IInstallableUnit> query = QueryUtil.createMatchQuery("id ~=/*org.eclipse.wst.server.core.serverAdapter/"); //$NON-NLS-1$
IMetadataRepository repo = manager.loadRepository(url2, monitor);
list = getInstallableUnits(repo,query,url2,monitor);
}
return list;
} catch (ProvisionException e) {
Trace.trace(Trace.WARNING, "Error getting update info", e); //$NON-NLS-1$
throw e;
}catch (Exception e) {
Trace.trace(Trace.WARNING, "Error getting update info", e); //$NON-NLS-1$
return new ArrayList<IServerExtension>(0);
}
finally {
if (url2 != null && url2.getPath().length() != 0 && manager != null) {
if (existingSites != null && existingSites.length > 0) {
boolean urlExists = false;
for (URI uri : existingSites) {
if (uri.getPath().equals(url2.getPath())){
urlExists = true;
break;
}
}
// If site did not exist before, remove it as it was added with load
if (!urlExists) {
manager.removeRepository(url2);
}
}
}
}
}
// Get the list of InstallableUnits and all its requirements
protected List<IServerExtension> getInstallableUnits(IMetadataRepository repo, IQuery<IInstallableUnit> query, URI url, IProgressMonitor monitor){
List<IServerExtension> list = new ArrayList<IServerExtension>();
IQueryResult<IInstallableUnit> collector = repo.query(query, monitor);
for (IInstallableUnit iu: collector.toUnmodifiableSet()) {
Collection<IRequirement> req = iu.getRequirements();
if (req != null) {
for (IRequirement requirement : req) {
IMatchExpression<IInstallableUnit> matches = requirement.getMatches();
query = new ExpressionMatchQuery<IInstallableUnit>(IInstallableUnit.class, matches);
IQueryResult<IInstallableUnit> collector2 = repo.query(query, monitor);
Iterator<IInstallableUnit> iter2 = collector2.iterator();
while (iter2.hasNext()) {
IInstallableUnit iu2 = iter2.next();
if (!list.contains(iu2)) {
Extension ext = new Extension(iu2, url);
list.add(ext);
}
}
}
}
}
return list;
}
}