| package org.eclipse.scout.sdk.compatibility.v37v41.internal; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Set; |
| |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.URIUtil; |
| import org.eclipse.pde.internal.core.target.ExternalFileTargetHandle; |
| import org.eclipse.pde.internal.core.target.IUBundleContainer; |
| import org.eclipse.pde.internal.core.target.TargetDefinitionPersistenceHelper; |
| import org.eclipse.pde.internal.core.target.WorkspaceFileTargetHandle; |
| import org.eclipse.pde.internal.core.target.provisional.IBundleContainer; |
| import org.eclipse.pde.internal.core.target.provisional.ITargetDefinition; |
| import org.eclipse.pde.internal.core.target.provisional.ITargetHandle; |
| import org.eclipse.pde.internal.core.target.provisional.ITargetPlatformService; |
| import org.eclipse.pde.internal.core.target.provisional.NameVersionDescriptor; |
| import org.eclipse.scout.sdk.compatibility.P2Utility; |
| import org.eclipse.scout.sdk.compatibility.internal.FeatureDefinition; |
| import org.eclipse.scout.sdk.compatibility.PlatformVersionUtility; |
| import org.eclipse.scout.sdk.compatibility.internal.ScoutCompatibilityActivator; |
| import org.eclipse.scout.sdk.compatibility.internal.service.ITargetPlatformCompatService; |
| import org.eclipse.scout.sdk.compatibility.v37v41.internal.provisional.LoadTargetDefinitionJobSync; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| |
| @SuppressWarnings("restriction") |
| public class TargetPlatformCompatService implements ITargetPlatformCompatService { |
| |
| private interface ITargetFileModification { |
| void contribute(List<IBundleContainer> liveList, Map<IUBundleContainer, Set<FeatureDefinition>> features, ITargetPlatformService svc) throws CoreException; |
| } |
| |
| @Override |
| public IStatus resolveTargetPlatform(IFile targetFile, boolean loadPlatform, IProgressMonitor monitor) throws CoreException { |
| ITargetPlatformService targetService = ScoutCompatibilityActivator.getDefault().acquireService(ITargetPlatformService.class); |
| ITargetHandle handle = targetService.getTarget(targetFile); |
| ITargetDefinition def = handle.getTargetDefinition(); |
| return resolveTarget(def, loadPlatform, monitor); |
| } |
| |
| @Override |
| public URI getCurrentTargetFile() throws CoreException { |
| ITargetPlatformService targetService = ScoutCompatibilityActivator.getDefault().acquireService(ITargetPlatformService.class); |
| ITargetHandle workspaceTargetHandle = targetService.getWorkspaceTargetHandle(); |
| if (workspaceTargetHandle instanceof WorkspaceFileTargetHandle && workspaceTargetHandle.exists()) { |
| IFile f = ((WorkspaceFileTargetHandle) workspaceTargetHandle).getTargetFile(); |
| if (f != null && f.exists()) { |
| return f.getLocationURI(); |
| } |
| } |
| else if (workspaceTargetHandle instanceof ExternalFileTargetHandle && workspaceTargetHandle.exists()) { |
| return ((ExternalFileTargetHandle) workspaceTargetHandle).getLocation(); |
| } |
| return null; |
| } |
| |
| @Override |
| public IStatus resolveTargetPlatform(Set<File> absolutePaths, String targetName, boolean loadPlatform, IProgressMonitor monitor) throws CoreException { |
| ITargetPlatformService tpService = ScoutCompatibilityActivator.getDefault().acquireService(ITargetPlatformService.class); |
| ITargetDefinition targetDef = tpService.newTarget(); |
| targetDef.setName(targetName); |
| |
| List<IBundleContainer> bundleContainers = new ArrayList<IBundleContainer>(); |
| for (File dir : absolutePaths) { |
| bundleContainers.add(tpService.newDirectoryContainer(dir.getAbsolutePath())); |
| } |
| targetDef.setBundleContainers(bundleContainers.toArray(new IBundleContainer[bundleContainers.size()])); |
| targetDef.setArch(Platform.getOSArch()); |
| targetDef.setOS(Platform.getOS()); |
| targetDef.setWS(Platform.getWS()); |
| targetDef.setNL(Platform.getNL()); |
| tpService.saveTargetDefinition(targetDef); |
| |
| return resolveTarget(targetDef, loadPlatform, monitor); |
| } |
| |
| private IStatus resolveTarget(ITargetDefinition def, boolean loadPlatform, IProgressMonitor monitor) { |
| IStatus result = def.resolve(monitor); |
| if (loadPlatform && result.isOK()) { |
| LoadTargetDefinitionJobSync loadJob = new LoadTargetDefinitionJobSync(def); |
| result = loadJob.run(monitor); |
| } |
| return result; |
| } |
| |
| @Override |
| public void removeInstallableUnitsFromTarget(IFile targetFile, final String[] unitIds) throws CoreException { |
| modifyTargetFile(targetFile, new ITargetFileModification() { |
| @Override |
| public void contribute(List<IBundleContainer> liveList, Map<IUBundleContainer, Set<FeatureDefinition>> features, ITargetPlatformService svc) throws CoreException { |
| for (Set<FeatureDefinition> featureOfContainer : features.values()) { |
| Iterator<FeatureDefinition> it = featureOfContainer.iterator(); |
| while (it.hasNext()) { |
| FeatureDefinition def = it.next(); |
| for (String featureToRemove : unitIds) { |
| if (featureToRemove != null && featureToRemove.equals(def.id)) { |
| it.remove(); |
| } |
| } |
| } |
| } |
| } |
| }); |
| } |
| |
| @Override |
| public void addDirectoryLocationToTarget(IFile targetFile, final String[] dirs) throws CoreException { |
| modifyTargetFile(targetFile, new ITargetFileModification() { |
| @Override |
| public void contribute(List<IBundleContainer> liveList, Map<IUBundleContainer, Set<FeatureDefinition>> features, ITargetPlatformService svc) { |
| for (String dir : dirs) { |
| if (dir != null && dir.trim().length() > 0) { |
| liveList.add(svc.newDirectoryContainer(dir)); |
| } |
| } |
| } |
| }); |
| } |
| |
| @Override |
| public void addInstallableUnitToTarget(IFile targetFile, final String unitId, final String version, final String repository, final IProgressMonitor monitor) throws CoreException { |
| modifyTargetFile(targetFile, new ITargetFileModification() { |
| @Override |
| public void contribute(List<IBundleContainer> liveList, Map<IUBundleContainer, Set<FeatureDefinition>> features, ITargetPlatformService svc) throws CoreException { |
| try { |
| String ver = version; |
| if (ver == null || ver.trim().length() < 1) { |
| ver = P2Utility.getLatestVersion(unitId, URIUtil.fromString(repository), monitor); |
| } |
| |
| IUBundleContainer container = getContainer(repository, features.keySet()); |
| FeatureDefinition fd = new FeatureDefinition(); |
| fd.id = unitId; |
| fd.version = ver; |
| if (container == null) { |
| URI uri = URIUtil.fromString(repository); |
| IUBundleContainer newIULocation = (IUBundleContainer) svc.newIUContainer(new String[]{unitId}, new String[]{ver}, new URI[]{uri}, 0); |
| Set<FeatureDefinition> set = new HashSet<FeatureDefinition>(1); |
| set.add(fd); |
| features.put(newIULocation, set); |
| } |
| else { |
| features.get(container).add(fd); |
| } |
| } |
| catch (URISyntaxException e) { |
| throw new CoreException(new Status(IStatus.ERROR, ScoutCompatibilityActivator.PLUGIN_ID, "Unable to parse url '" + repository + "'.", e)); |
| } |
| } |
| }); |
| } |
| |
| // |
| // @Override |
| // public void addInstallableUnitsToTarget(IFile targetFile, String[] unitIds, String[] versions, String[] repositories) throws CoreException { |
| // URI[] uris = new URI[repositories.length]; |
| // try { |
| // for (int i = 0; i < repositories.length; i++) { |
| // uris[i] = new URI(repositories[i]); |
| // } |
| // } |
| // catch (URISyntaxException e) { |
| // throw new CoreException(new Status(IStatus.ERROR, ScoutCompatibilityActivator.PLUGIN_ID, "invalid URI provided", e)); |
| // } |
| // |
| // ITargetPlatformService svc = ScoutCompatibilityActivator.getDefault().acquireService(ITargetPlatformService.class); |
| // ITargetHandle handle = svc.getTarget(targetFile); |
| // ITargetDefinition td = handle.getTargetDefinition(); |
| // IBundleContainer[] features = td.getBundleContainers(); |
| // |
| // int s = unitIds.length; |
| // if (features != null) { |
| // s += features.length; |
| // } |
| // ArrayList<IBundleContainer> newList = new ArrayList<IBundleContainer>(s); |
| // if (features != null && features.length > 0) { |
| // for (IBundleContainer container : features) { |
| // newList.add(container); |
| // } |
| // } |
| // for (int i = 0; i < unitIds.length; i++) { |
| // IUBundleContainer group = (IUBundleContainer) svc.newIUContainer(new String[]{unitIds[i]}, new String[]{versions[i]}, new URI[]{uris[i]}, |
| // IUBundleContainer.INCLUDE_SOURCE); |
| // newList.add(group); |
| // } |
| // td.setBundleContainers(newList.toArray(new IBundleContainer[newList.size()])); |
| // svc.saveTargetDefinition(td); |
| // } |
| |
| /** |
| * workaround for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=432494 |
| */ |
| private Set<FeatureDefinition> getValueOf(Map<IUBundleContainer, Set<FeatureDefinition>> map, IUBundleContainer objectToFind) { |
| for (Entry<IUBundleContainer, Set<FeatureDefinition>> entry : map.entrySet()) { |
| if (objectToFind != null && objectToFind.equals(entry.getKey())) { |
| return entry.getValue(); |
| } |
| } |
| return null; |
| } |
| |
| private boolean isRepository(Element location, IUBundleContainer iubc) throws URISyntaxException { |
| final String REPOSITORY = "repository"; // from org.eclipse.pde.internal.core.target.TargetDefinitionPersistenceHelper.REPOSITORY |
| final String ATTR_LOCATION = "location"; |
| NodeList repositories = location.getElementsByTagName(REPOSITORY); |
| for (int i = 0; i < repositories.getLength(); i++) { |
| Element candidate = (Element) repositories.item(i); |
| if (candidate.hasAttribute(ATTR_LOCATION)) { |
| String loc = candidate.getAttribute(ATTR_LOCATION); |
| URI uri = URIUtil.fromString(loc); |
| for (URI repoUri : iubc.getRepositories()) { |
| if (URIUtil.sameURI(uri, repoUri)) { |
| return true; |
| } |
| } |
| } |
| } |
| return false; |
| } |
| |
| private List<NameVersionDescriptor> getFeatures(IUBundleContainer iubc, Document document) throws URISyntaxException { |
| final String LOCATION = "location"; // from org.eclipse.pde.internal.core.target.TargetDefinitionPersistenceHelper.LOCATION |
| final String INSTALLABLE_UNIT = "unit"; // from org.eclipse.pde.internal.core.target.TargetDefinitionPersistenceHelper.INSTALLABLE_UNIT |
| final String ATTR_ID = "id"; // from org.eclipse.pde.internal.core.target.TargetDefinitionPersistenceHelper.ATTR_ID |
| final String ATTR_VERSION = "version"; // from org.eclipse.pde.internal.core.target.TargetDefinitionPersistenceHelper.ATTR_VERSION |
| |
| NodeList locations = document.getDocumentElement().getElementsByTagName(LOCATION); |
| ArrayList<NameVersionDescriptor> result = new ArrayList<NameVersionDescriptor>(locations.getLength()); |
| for (int i = 0; i < locations.getLength(); i++) { |
| Element location = (Element) locations.item(i); |
| if (isRepository(location, iubc)) { |
| NodeList childNodes = location.getChildNodes(); |
| for (int j = 0; j < childNodes.getLength(); j++) { |
| Node nn = childNodes.item(j); |
| if (nn.getNodeType() == Node.ELEMENT_NODE && INSTALLABLE_UNIT.equals(nn.getNodeName())) { |
| Element e = (Element) nn; |
| if (e.hasAttribute(ATTR_ID)) { |
| String id = e.getAttribute(ATTR_ID); |
| String version = e.getAttribute(ATTR_VERSION); |
| result.add(new NameVersionDescriptor(id, version)); |
| } |
| } |
| } |
| } |
| } |
| return result; |
| } |
| |
| private static IUBundleContainer getContainer(String uri, Set<IUBundleContainer> containers) throws URISyntaxException { |
| URI searchUri = URIUtil.fromString(uri); |
| for (IUBundleContainer container : containers) { |
| for (URI repo : container.getRepositories()) { |
| if (URIUtil.sameURI(searchUri, repo)) { |
| return container; |
| } |
| } |
| } |
| return null; |
| } |
| |
| private void modifyTargetFile(IFile targetFile, ITargetFileModification modification) throws CoreException { |
| final String encoding = "UTF-8"; |
| ITargetPlatformService svc = ScoutCompatibilityActivator.getDefault().acquireService(ITargetPlatformService.class); |
| ITargetHandle handle = svc.getTarget(targetFile); |
| ITargetDefinition td = handle.getTargetDefinition(); |
| IBundleContainer[] features = td.getBundleContainers(); |
| int size = 1; |
| if (features != null) { |
| size += features.length; |
| } |
| |
| try { |
| ByteArrayOutputStream out = new ByteArrayOutputStream(); |
| TargetDefinitionPersistenceHelper.persistXML(td, out); |
| String xml = out.toString(encoding); |
| DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); |
| Document document = docBuilder.parse(new ByteArrayInputStream(xml.getBytes(encoding))); |
| |
| Map<IUBundleContainer, Set<FeatureDefinition>> p2FeatureMap = new HashMap<IUBundleContainer, Set<FeatureDefinition>>(size); |
| List<IBundleContainer> locations = new ArrayList<IBundleContainer>(size); |
| if (features != null) { |
| for (IBundleContainer container : features) { |
| if (container instanceof IUBundleContainer) { |
| IUBundleContainer iubc = (IUBundleContainer) container; |
| List<NameVersionDescriptor> fs = getFeatures(iubc, document); |
| |
| Set<FeatureDefinition> featureSet = getValueOf(p2FeatureMap, iubc); |
| if (featureSet == null) { |
| featureSet = new HashSet<FeatureDefinition>(fs.size()); |
| p2FeatureMap.put(iubc, featureSet); |
| } |
| |
| for (NameVersionDescriptor f : fs) { |
| FeatureDefinition fd = new FeatureDefinition(); |
| fd.id = f.getId(); |
| fd.version = f.getVersion(); |
| featureSet.add(fd); |
| } |
| } |
| else { |
| locations.add(container); |
| } |
| } |
| } |
| |
| modification.contribute(locations, p2FeatureMap, svc); |
| |
| for (Entry<IUBundleContainer, Set<FeatureDefinition>> entry : p2FeatureMap.entrySet()) { |
| if (!entry.getValue().isEmpty()) { |
| String[] unitIds = new String[entry.getValue().size()]; |
| String[] versions = new String[entry.getValue().size()]; |
| int i = 0; |
| for (FeatureDefinition f : entry.getValue()) { |
| unitIds[i] = f.id; |
| if (f.version == null) { |
| versions[i] = PlatformVersionUtility.EMPTY_VERSION_STR; |
| } |
| else { |
| versions[i] = f.version; |
| } |
| i++; |
| } |
| |
| locations.add(svc.newIUContainer(unitIds, versions, entry.getKey().getRepositories(), IUBundleContainer.INCLUDE_SOURCE)); |
| } |
| } |
| |
| td.setBundleContainers(locations.toArray(new IBundleContainer[locations.size()])); |
| svc.saveTargetDefinition(td); |
| } |
| catch (Exception e) { |
| throw new CoreException(new Status(IStatus.ERROR, ScoutCompatibilityActivator.PLUGIN_ID, "Unable to parse installable units.", e)); |
| } |
| } |
| } |