blob: 075f8466781c573aa06c41bb97940f1a4ec21e89 [file] [log] [blame]
/*
* Copyright (c) 2016, 2017 Ed Merks (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Ed Merks - initial API and implementation
*/
package org.eclipse.oomph.setup.internal.core.util;
import org.eclipse.oomph.base.Annotation;
import org.eclipse.oomph.base.BaseFactory;
import org.eclipse.oomph.base.BasePackage;
import org.eclipse.oomph.base.util.ArchiveResourceImpl;
import org.eclipse.oomph.base.util.BaseResourceFactoryImpl;
import org.eclipse.oomph.base.util.BaseUtil;
import org.eclipse.oomph.internal.setup.SetupProperties;
import org.eclipse.oomph.setup.Index;
import org.eclipse.oomph.setup.internal.core.SetupContext;
import org.eclipse.oomph.util.ObjectUtil;
import org.eclipse.oomph.util.PropertiesUtil;
import org.eclipse.oomph.util.StringUtil;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/**
* @author Ed Merks
*/
public class IndexManager
{
private static URI DEFAULT_INDEX_LOCATION = URI
.createURI("archive:http://www.eclipse.org/setups/setups.zip!/http/git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/org.eclipse.setup");
private final ResourceSet resourceSet = new ResourceSetImpl();
private final URI indicesLocation;
private final Resource indicesResource;
private final IndexManager globalIndexManager;
public IndexManager()
{
this(SetupContext.CONFIGURATION_STATE_LOCATION_URI.appendSegment("indices.xmi"),
new IndexManager(SetupContext.GLOBAL_SETUPS_LOCATION_URI.appendSegment("indices.xmi"), null));
}
private IndexManager(URI indicesLocation, IndexManager globalIndexManager)
{
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", new BaseResourceFactoryImpl());
this.indicesLocation = indicesLocation;
indicesResource = resourceSet.createResource(indicesLocation);
this.globalIndexManager = globalIndexManager;
}
public IndexManager getGlobalIndexManager()
{
return globalIndexManager;
}
public boolean addIndex(Index index)
{
Resource resource = index.eResource();
URI uri = resource.getURI();
URIConverter uriConverter = resource.getResourceSet().getURIConverter();
URI indexLocation = uriConverter.normalize(uri);
return addIndex(indexLocation, index.getName(), false);
}
public boolean addIndex(URI indexLocation, String name, boolean local)
{
if (!local && globalIndexManager != null)
{
globalIndexManager.addIndex(indexLocation, name, true);
}
Annotation annotation = getAnnotation();
EMap<String, String> details = annotation.getDetails();
String oldName = details.put(indexLocation.toString(), name);
int entryIndex = details.indexOfKey(indexLocation.toString());
if (entryIndex != 0)
{
details.move(0, entryIndex);
}
save(annotation);
return !ObjectUtil.equals(oldName, name);
}
public void remove(URI indexLocation, boolean local)
{
if (!local && globalIndexManager != null)
{
globalIndexManager.remove(indexLocation, true);
}
Annotation annotation = getAnnotation();
Annotation labelsAnnotation = annotation.getAnnotation("labels");
annotation.getDetails().removeKey(indexLocation.toString());
if (labelsAnnotation != null)
{
labelsAnnotation.getDetails().removeKey(indexLocation.toString());
}
save(annotation);
}
public void setLabel(URI indexLocation, String label, boolean local)
{
if (!local && globalIndexManager != null)
{
globalIndexManager.setLabel(indexLocation, label, true);
}
Annotation annotation = getAnnotation();
Annotation labelsAnnotation = annotation.getAnnotation("labels");
if (labelsAnnotation == null)
{
labelsAnnotation = BaseFactory.eINSTANCE.createAnnotation();
labelsAnnotation.setSource("labels");
annotation.getAnnotations().add(labelsAnnotation);
}
labelsAnnotation.getDetails().put(indexLocation.toString(), label);
save(annotation);
}
public void configure(ResourceSet resourceSet)
{
// If there are any filter properties in place, we have to assume that we're in a crippled installer
// or in an application that has specified exactly the index they want to use in this application,
// so don't switch the most recently used index in this case.
if (StringUtil.isEmpty(PropertiesUtil.getProperty(SetupProperties.PROP_SETUP_PRODUCT_CATALOG_FILTER))
&& StringUtil.isEmpty(PropertiesUtil.getProperty(SetupProperties.PROP_SETUP_PRODUCT_FILTER))
&& StringUtil.isEmpty(PropertiesUtil.getProperty(SetupProperties.PROP_SETUP_PRODUCT_VERSION_FILTER)))
{
// If the resource set is configured to use the default location...
URI currentIndexLocation = resourceSet.getURIConverter().normalize(SetupContext.INDEX_SETUP_URI);
if (currentIndexLocation.equals(DEFAULT_INDEX_LOCATION) || currentIndexLocation.equals(SetupContext.INDEX_SETUP_LOCATION_URI))
{
// If there are indices in the local indices.xmi...
Annotation annotation = getAnnotation();
EMap<String, String> details = annotation.getDetails();
if (!details.isEmpty())
{
// If the first index location is different from the default location (which is already configured in the given resource set)
// and the current index location is also already in present,
// only then configure the resource set to use the first location,
// which is the most recently used index for this application,
// or, if it's the first time this application is executed,
// the most recently used index for any application on this machine.
URI indexLocation = URI.createURI(details.get(0).getKey());
if (!indexLocation.equals(DEFAULT_INDEX_LOCATION) && currentIndexLocation.equals(SetupContext.INDEX_SETUP_LOCATION_URI)
|| details.containsKey(currentIndexLocation.toString()) && !currentIndexLocation.equals(indexLocation))
{
configureForProxy(resourceSet, indexLocation);
}
}
}
}
}
public void configureForProxy(ResourceSet resourceSet, URI indexLocation)
{
// If the index location is an entry in an archive...
if (indexLocation.isArchive())
{
// Configure for the resource set for the underlying archive as the whole.
String authority = indexLocation.authority();
URI archiveLocation = URI.createURI(authority.substring(0, authority.length() - 1));
configure(resourceSet, archiveLocation);
}
else
{
// Configure the resource set to use the default archive location,
// which the client may have already redirected in this resource set.
configure(resourceSet, SetupContext.INDEX_SETUP_ARCHIVE_LOCATION_URI);
// Add a URI mapping to ensure that index folder maps to the folder of the specified index location.
Map<URI, URI> uriMap = resourceSet.getURIConverter().getURIMap();
uriMap.put(SetupContext.INDEX_ROOT_URI, indexLocation.trimSegments(1).appendSegment(""));
}
}
public void configure(ResourceSet resourceSet, URI setupArchiveURI)
{
// Load the entry information in the archive.
Resource archiveResource = new ArchiveResourceImpl(setupArchiveURI, resourceSet.getURIConverter());
try
{
archiveResource.load(null);
}
catch (IOException ex)
{
// Ignore.
}
// This will be represented as an annotation.
Annotation annotation = (Annotation)EcoreUtil.getObjectByType(archiveResource.getContents(), BasePackage.Literals.ANNOTATION);
if (annotation != null && !annotation.getDetails().isEmpty())
{
// Clear any previous redirections and reestablish a clean set of redirections.
URIConverter uriConverter = resourceSet.getURIConverter();
Map<URI, URI> uriMap = uriConverter.getURIMap();
uriMap.clear();
SetupCoreUtil.configureRedirections(uriMap);
// Redirect the default archive location to this archive's location.
uriMap.put(SetupContext.INDEX_SETUP_ARCHIVE_LOCATION_URI, setupArchiveURI);
for (Map.Entry<String, String> entry : annotation.getDetails())
{
// Add mappings for each entry.
URI sourceURI = URI.createURI(entry.getKey());
if (sourceURI.equals(uriConverter.normalize(sourceURI)))
{
URI targtURI = URI.createURI(entry.getValue());
uriMap.put(sourceURI, targtURI);
// If this is the index resource itself...
if (SetupContext.INDEX_SETUP_NAME.equals(sourceURI.lastSegment()))
{
// Map the index location to this location,
// map the folder of the index location to this location's folder,
// and map the whole index folder to this locations's folder.
// This brute force approach is most likely to fully override any mappings that might already be in place in the resource set.
uriMap.put(SetupContext.INDEX_SETUP_LOCATION_URI, targtURI);
uriMap.put(SetupContext.INDEX_ROOT_LOCATION_URI, targtURI.trimSegments(1).appendSegment(""));
uriMap.put(SetupContext.INDEX_ROOT_URI, targtURI.trimSegments(1).appendSegment(""));
}
}
}
}
}
public Map<URI, String> getIndexNames(boolean local)
{
Map<URI, String> result = new LinkedHashMap<URI, String>();
Annotation annotation = getAnnotation();
for (Map.Entry<String, String> detail : annotation.getDetails())
{
String name = detail.getValue();
if (StringUtil.isEmpty(name))
{
name = "<unnamed-index>";
}
result.put(URI.createURI(detail.getKey()), name);
}
if (!local && globalIndexManager != null)
{
for (Map.Entry<URI, String> entry : globalIndexManager.getIndexNames(true).entrySet())
{
if (!result.containsKey(entry.getKey()))
{
result.put(entry.getKey(), entry.getValue());
}
}
}
return result;
}
public Map<URI, String> getIndexLabels(boolean local)
{
Annotation annotation = getAnnotation();
Annotation labelsAnnotation = annotation.getAnnotation("labels");
Map<URI, String> result = new LinkedHashMap<URI, String>();
Set<String> labels = new HashSet<String>();
Set<String> duplicates = new HashSet<String>();
for (Map.Entry<String, String> detail : annotation.getDetails())
{
String label = null;
String indexLocation = detail.getKey();
if (labelsAnnotation != null)
{
label = labelsAnnotation.getDetails().get(indexLocation);
}
if (label == null)
{
String name = detail.getValue();
if (!labels.add(name))
{
duplicates.add(name);
}
}
result.put(URI.createURI(indexLocation), label);
}
for (Map.Entry<String, String> detail : annotation.getDetails())
{
URI indexLocation = URI.createURI(detail.getKey());
if (result.get(indexLocation) == null)
{
String itemText = detail.getValue();
if (StringUtil.isEmpty(itemText))
{
itemText = "<unnamed-index>";
}
if (duplicates.contains(itemText))
{
itemText += " - " + indexLocation;
}
result.put(indexLocation, itemText);
}
}
if (!local && globalIndexManager != null)
{
for (Map.Entry<URI, String> entry : globalIndexManager.getIndexLabels(true).entrySet())
{
if (!result.containsKey(entry.getKey()))
{
result.put(entry.getKey(), entry.getValue());
}
}
}
return result;
}
public Map<URI, Boolean> getIndexAvailability(boolean local)
{
Map<URI, Boolean> result = new LinkedHashMap<URI, Boolean>();
Set<URI> indexLocations = getIndexNames(local).keySet();
URIConverter uriConverter = resourceSet.getURIConverter();
for (URI indexLocation : indexLocations)
{
result.put(indexLocation, uriConverter.exists(indexLocation, null));
}
return result;
}
private Annotation getAnnotation()
{
BaseUtil.execute(5000, new Runnable()
{
public void run()
{
loadIndices();
}
}, resourceSet.getURIConverter(), indicesLocation);
Annotation annotation = (Annotation)EcoreUtil.getObjectByType(indicesResource.getContents(), BasePackage.Literals.ANNOTATION);
if (annotation == null)
{
annotation = createDefaultIndex();
}
return annotation;
}
private void loadIndices()
{
if (resourceSet.getURIConverter().exists(indicesLocation, null))
{
try
{
indicesResource.unload();
indicesResource.load(resourceSet.getLoadOptions());
}
catch (IOException ex)
{
// Ignore.
}
Annotation annotation = (Annotation)EcoreUtil.getObjectByType(indicesResource.getContents(), BasePackage.Literals.ANNOTATION);
if (annotation == null)
{
createDefaultIndex();
}
}
else
{
createDefaultIndex();
}
}
private Annotation createDefaultIndex()
{
Annotation annotation = null;
if (globalIndexManager != null)
{
annotation = globalIndexManager.getAnnotation();
if (annotation != null)
{
annotation = EcoreUtil.copy(annotation);
}
}
if (annotation == null)
{
ResourceSet configuredResourceSet = SetupCoreUtil.createResourceSet();
URI indexLocation = configuredResourceSet.getURIConverter().normalize(SetupContext.INDEX_SETUP_URI);
annotation = BaseFactory.eINSTANCE.createAnnotation();
annotation.setSource("IndexLocations");
EMap<String, String> details = annotation.getDetails();
details.put(indexLocation.toString(), "Eclipse");
}
EList<EObject> contents = indicesResource.getContents();
contents.clear();
contents.add(annotation);
return annotation;
}
private void save(final Annotation annotation)
{
BaseUtil.execute(5000, new Runnable()
{
public void run()
{
BaseUtil.saveEObject(annotation);
}
}, resourceSet.getURIConverter(), indicesLocation);
}
public static URI getUnderlyingLocation(URI indexLocation)
{
if (indexLocation.isArchive())
{
String authority = indexLocation.authority();
return URI.createURI(authority.substring(0, authority.length() - 1));
}
if (SetupContext.INDEX_SETUP_NAME.equals(indexLocation.lastSegment()))
{
return indexLocation.trimSegments(1).appendSegment("");
}
return indexLocation;
}
}