| /******************************************************************************* |
| * Copyright (c) 2000, 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.releng.tools; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IResourceChangeEvent; |
| import org.eclipse.core.resources.IResourceChangeListener; |
| import org.eclipse.core.resources.IResourceDelta; |
| import org.eclipse.core.resources.IWorkspace; |
| import org.eclipse.core.resources.IWorkspaceRoot; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.team.core.TeamException; |
| import org.eclipse.team.internal.ccvs.core.CVSTag; |
| import org.eclipse.team.internal.ccvs.core.client.Command; |
| import org.eclipse.team.internal.ccvs.ui.operations.CommitOperation; |
| import org.eclipse.team.internal.ccvs.ui.operations.RepositoryProviderOperation; |
| |
| |
| public class MapProject implements IResourceChangeListener { |
| |
| private static MapProject mapProject = null; |
| private IProject project; |
| private MapFile[] mapFiles; |
| |
| /** |
| * Return the default map project (org.eclipse.releng) or |
| * <code>null</code> if the project does not exist or there |
| * is an error processing it. If there is an error, it |
| * will be logged. |
| * @return the default map project |
| */ |
| public static MapProject getDefaultMapProject(){ |
| if (mapProject == null) { |
| IProject project = getProjectFromWorkspace(); |
| try { |
| mapProject = new MapProject(project); |
| } catch (CoreException e) { |
| RelEngPlugin.log(e); |
| } |
| } |
| return mapProject; |
| } |
| |
| private static IProject getProjectFromWorkspace() { |
| IWorkspace workspace = ResourcesPlugin.getWorkspace(); |
| IWorkspaceRoot root = workspace.getRoot(); |
| IProject project = root.getProject(RelEngPlugin.MAP_PROJECT_NAME); |
| return project; |
| } |
| |
| public MapProject(IProject p) throws CoreException { |
| this.project = p; |
| loadMapFiles(); |
| ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE); |
| } |
| |
| public IProject getProject() { |
| return project; |
| } |
| |
| public void setProject(IProject p){ |
| this.project = p; |
| } |
| |
| private MapFile getMapFile(IProject p){ |
| for (int i = 0; i< mapFiles.length; i++){ |
| if (mapFiles[i].contains(p)) { |
| return mapFiles[i]; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Return the MapEntry for the given project |
| * @param string |
| * @param string1 |
| */ |
| public MapEntry getMapEntry(IProject p) { |
| MapFile file = getMapFile(p); |
| if (file != null) { |
| return file.getMapEntry(p); |
| } |
| return null; |
| } |
| |
| public boolean mapsAreLoaded() { |
| return project.exists(); |
| } |
| |
| public MapFile[] getValidMapFiles(){ |
| List<MapFile> list = new ArrayList<>(); |
| for (int i = 0; i <mapFiles.length; i++){ |
| IProject[] projects = mapFiles[i].getAccessibleProjects(); |
| if( projects!= null && projects.length > 0){ |
| list.add(mapFiles[i]); |
| } |
| } |
| return list.toArray(new MapFile[list.size()]); |
| } |
| |
| /** |
| * @param aProject The map entry of the specified project will be changed to the specified tag |
| * @param tag The specified tag |
| * @return returns if no map file having such a map entry is found |
| */ |
| public void updateFile(IProject aProject, String tag) throws CoreException { |
| MapFile aFile = getMapFile(aProject); |
| if (aFile == null)return; |
| MapContentDocument changed = new MapContentDocument(aFile); |
| changed.updateTag(aProject, tag); |
| if (changed.isChanged()) { |
| aFile.getFile().setContents(changed.getContents(), IResource.KEEP_HISTORY, null); |
| } |
| } |
| |
| public void commitMapProject(String comment, IProgressMonitor monitor) throws CoreException{ |
| try { |
| new CommitOperation(null, RepositoryProviderOperation.asResourceMappers(new IResource[] { project }), new Command.LocalOption[0], comment).run(monitor); |
| } catch (InvocationTargetException e) { |
| throw TeamException.asTeamException(e); |
| } catch (InterruptedException e) { |
| // Ignore; |
| e.printStackTrace(); |
| } |
| } |
| |
| public MapFile[] getMapFilesFor(IProject[] projects){ |
| Set<MapFile> alist = new HashSet<>(); |
| for(int i = 0; i<projects.length; i++){ |
| MapFile aMapFile = getMapFile(projects[i]); |
| alist.add(aMapFile); |
| } |
| return alist.toArray(new MapFile[alist.size()]); |
| } |
| |
| /** |
| * Get the tags for the given projects. If no tag is found |
| * for whatever reason, HEAD is used. |
| * @param projects |
| * @return |
| */ |
| public CVSTag[] getTagsFor(IProject[] projects){ |
| if(projects == null || projects.length == 0)return null; |
| CVSTag[] tags = new CVSTag[projects.length]; |
| for (int i = 0; i < tags.length; i++){ |
| MapEntry entry = getMapEntry(projects[i]); |
| if (entry == null) tags[i] = CVSTag.DEFAULT; |
| else tags[i] = entry.getTag(); |
| } |
| return tags; |
| } |
| /** |
| * Deregister the IResourceChangeListner. It is reserved for use in the future. It is never called |
| * for now |
| */ |
| public void dispose(){ |
| ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); |
| mapFiles= null; |
| } |
| |
| /** |
| * @see IResourceChangeListener#resourceChanged(IResourceChangeEvent) |
| */ |
| @Override |
| public void resourceChanged(IResourceChangeEvent event) { |
| IResourceDelta root = event.getDelta(); |
| |
| //TODO: Need to add code to handle map project deletion, addition and rename |
| IResourceDelta folderDelta = root.findMember(getMapFolder().getFullPath()); |
| if (folderDelta == null) return; |
| |
| //Handle map files deletion, addition and rename |
| IResourceDelta[] deltas = folderDelta.getAffectedChildren(); |
| if(deltas == null || deltas.length == 0) return; |
| for (int i = 0; i < deltas.length; i++) { |
| IResourceDelta delta = deltas[i]; |
| if(delta.getResource().getType() == IResource.FILE){ |
| try{ |
| IFile aFile = (IFile)(delta.getResource()); |
| MapFile mFile = null; |
| if(MapFile.isMapFile(aFile)){ |
| // Handle content change |
| if(delta.getKind() == IResourceDelta.CHANGED){ |
| mFile = getMapFileFor(aFile); |
| mFile.loadEntries(); |
| } |
| //Handle deletion. We cannot simply remove the map file directly bacause we have to call |
| //getMapFileFor(IFile) in order to do so. But the IFile is already deleted. So we have to |
| //reconstuct the map files. |
| if(delta.getKind() == IResourceDelta.REMOVED ){ |
| loadMapFiles(); |
| } |
| // Handle addition |
| if(delta.getKind() == IResourceDelta.ADDED ){ |
| mFile = getMapFileFor(aFile); |
| addMapFile(mFile); |
| } |
| } |
| } catch (CoreException e) { |
| RelEngPlugin.log(e); |
| } |
| } |
| } |
| } |
| |
| private IFolder getMapFolder(){ |
| return getProject().getFolder(RelEngPlugin.MAP_FOLDER); |
| } |
| |
| private void loadMapFiles() throws CoreException { |
| mapFiles = MapFile.findAllMapFiles(project); |
| } |
| |
| private MapFile getMapFileFor(IFile file) throws CoreException{ |
| for(int i = 0; i < mapFiles.length; i++){ |
| if (mapFiles[i].getFile().equals(file)) |
| return mapFiles[i]; |
| } |
| return new MapFile(file); |
| } |
| private void addMapFile(MapFile aFile){ |
| Set<MapFile> set = new HashSet<>(Arrays.asList(mapFiles)); |
| set.add(aFile); |
| mapFiles = set.toArray(new MapFile[set.size()]); |
| } |
| } |