Java tutorial
/******************************************************************************* * Copyright (c) 2010 SAP AG. * 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: * Mathias Kinzler (SAP AG) - initial implementation *******************************************************************************/ package org.eclipse.egit.ui.internal.repository; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.Map.Entry; import org.eclipse.core.commands.IStateListener; import org.eclipse.core.commands.State; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.egit.core.RepositoryCache; import org.eclipse.egit.core.RepositoryUtil; import org.eclipse.egit.ui.Activator; import org.eclipse.egit.ui.UIText; import org.eclipse.egit.ui.internal.repository.tree.BranchHierarchyNode; import org.eclipse.egit.ui.internal.repository.tree.BranchesNode; import org.eclipse.egit.ui.internal.repository.tree.ErrorNode; import org.eclipse.egit.ui.internal.repository.tree.FetchNode; import org.eclipse.egit.ui.internal.repository.tree.FileNode; import org.eclipse.egit.ui.internal.repository.tree.FolderNode; import org.eclipse.egit.ui.internal.repository.tree.LocalNode; import org.eclipse.egit.ui.internal.repository.tree.AdditionalRefNode; import org.eclipse.egit.ui.internal.repository.tree.AdditionalRefsNode; import org.eclipse.egit.ui.internal.repository.tree.PushNode; import org.eclipse.egit.ui.internal.repository.tree.RefNode; import org.eclipse.egit.ui.internal.repository.tree.RemoteNode; import org.eclipse.egit.ui.internal.repository.tree.RemoteTrackingNode; import org.eclipse.egit.ui.internal.repository.tree.RemotesNode; import org.eclipse.egit.ui.internal.repository.tree.RepositoryNode; import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNode; import org.eclipse.egit.ui.internal.repository.tree.TagNode; import org.eclipse.egit.ui.internal.repository.tree.TagsNode; import org.eclipse.egit.ui.internal.repository.tree.WorkingDirNode; import org.eclipse.egit.ui.internal.repository.tree.command.ToggleBranchHierarchyCommand; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.RefDatabase; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.transport.RemoteConfig; import org.eclipse.jgit.transport.URIish; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.commands.ICommandService; /** * Content Provider for the Git Repositories View */ public class RepositoriesViewContentProvider implements ITreeContentProvider, IStateListener { private final RepositoryCache repositoryCache = org.eclipse.egit.core.Activator.getDefault() .getRepositoryCache(); private final State commandState; private boolean branchHierarchyMode = false; /** * Constructs this instance */ public RepositoriesViewContentProvider() { ICommandService srv = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); commandState = srv.getCommand(ToggleBranchHierarchyCommand.ID) .getState(ToggleBranchHierarchyCommand.TOGGLE_STATE); commandState.addListener(this); try { this.branchHierarchyMode = ((Boolean) commandState.getValue()).booleanValue(); } catch (Exception e) { Activator.handleError(e.getMessage(), e, false); } } @SuppressWarnings("unchecked") public Object[] getElements(Object inputElement) { List<RepositoryTreeNode> nodes = new ArrayList<RepositoryTreeNode>(); List<String> directories = new ArrayList<String>(); RepositoryUtil repositoryUtil = Activator.getDefault().getRepositoryUtil(); if (inputElement instanceof Collection) { for (Iterator it = ((Collection) inputElement).iterator(); it.hasNext();) { Object next = it.next(); if (next instanceof RepositoryTreeNode) nodes.add((RepositoryTreeNode) next); else if (next instanceof String) directories.add((String) next); } } else if (inputElement instanceof IWorkspaceRoot) { directories.addAll(repositoryUtil.getConfiguredRepositories()); } for (String directory : directories) { try { File gitDir = new File(directory); if (gitDir.exists()) { RepositoryNode rNode = new RepositoryNode(null, repositoryCache.lookupRepository(gitDir)); nodes.add(rNode); } else repositoryUtil.removeDir(gitDir); } catch (IOException e) { // ignore for now } } Collections.sort(nodes); return nodes.toArray(); } public void dispose() { commandState.removeListener(this); } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // nothing } public Object[] getChildren(Object parentElement) { RepositoryTreeNode node = (RepositoryTreeNode) parentElement; Repository repo = node.getRepository(); switch (node.getType()) { case BRANCHES: { List<RepositoryTreeNode> nodes = new ArrayList<RepositoryTreeNode>(); nodes.add(new LocalNode(node, repo)); nodes.add(new RemoteTrackingNode(node, repo)); return nodes.toArray(); } case LOCAL: { if (branchHierarchyMode) { BranchHierarchyNode hierNode = new BranchHierarchyNode(node, repo, new Path(Constants.R_HEADS)); List<RepositoryTreeNode> children = new ArrayList<RepositoryTreeNode>(); try { for (IPath path : hierNode.getChildPaths()) { children.add(new BranchHierarchyNode(node, node.getRepository(), path)); } for (Ref ref : hierNode.getChildRefs()) { children.add(new RefNode(node, node.getRepository(), ref)); } } catch (IOException e) { return handleException(e, node); } return children.toArray(); } else { List<RepositoryTreeNode<Ref>> refs = new ArrayList<RepositoryTreeNode<Ref>>(); try { for (Entry<String, Ref> refEntry : repo.getRefDatabase().getRefs(Constants.R_HEADS) .entrySet()) { if (!refEntry.getValue().isSymbolic()) refs.add(new RefNode(node, repo, refEntry.getValue())); } } catch (IOException e) { return handleException(e, node); } return refs.toArray(); } } case REMOTETRACKING: { if (branchHierarchyMode) { BranchHierarchyNode hierNode = new BranchHierarchyNode(node, repo, new Path(Constants.R_REMOTES)); List<RepositoryTreeNode> children = new ArrayList<RepositoryTreeNode>(); try { for (IPath path : hierNode.getChildPaths()) { children.add(new BranchHierarchyNode(node, node.getRepository(), path)); } for (Ref ref : hierNode.getChildRefs()) { children.add(new RefNode(node, node.getRepository(), ref)); } } catch (IOException e) { return handleException(e, node); } return children.toArray(); } else { List<RepositoryTreeNode<Ref>> refs = new ArrayList<RepositoryTreeNode<Ref>>(); try { for (Entry<String, Ref> refEntry : repo.getRefDatabase().getRefs(Constants.R_REMOTES) .entrySet()) { if (!refEntry.getValue().isSymbolic()) refs.add(new RefNode(node, repo, refEntry.getValue())); } } catch (IOException e) { return handleException(e, node); } return refs.toArray(); } } case BRANCHHIERARCHY: { BranchHierarchyNode hierNode = (BranchHierarchyNode) node; List<RepositoryTreeNode> children = new ArrayList<RepositoryTreeNode>(); try { for (IPath path : hierNode.getChildPaths()) { children.add(new BranchHierarchyNode(node, node.getRepository(), path)); } for (Ref ref : hierNode.getChildRefs()) { children.add(new RefNode(node, node.getRepository(), ref)); } } catch (IOException e) { return handleException(e, node); } return children.toArray(); } case TAGS: { List<RepositoryTreeNode<Ref>> refs = new ArrayList<RepositoryTreeNode<Ref>>(); try { for (Entry<String, Ref> refEntry : repo.getRefDatabase().getRefs(Constants.R_TAGS).entrySet()) { refs.add(new TagNode(node, repo, refEntry.getValue())); } } catch (IOException e) { return handleException(e, node); } return refs.toArray(); } case ADDITIONALREFS: { List<RepositoryTreeNode<Ref>> refs = new ArrayList<RepositoryTreeNode<Ref>>(); try { for (Entry<String, Ref> refEntry : repo.getRefDatabase().getRefs(RefDatabase.ALL).entrySet()) { String name = refEntry.getKey(); if (!(name.startsWith(Constants.R_HEADS) || name.startsWith(Constants.R_TAGS) || name.startsWith(Constants.R_REMOTES))) refs.add(new AdditionalRefNode(node, repo, refEntry.getValue())); } for (Ref r : repo.getRefDatabase().getAdditionalRefs()) refs.add(new AdditionalRefNode(node, repo, r)); } catch (IOException e) { return handleException(e, node); } return refs.toArray(); } case REMOTES: { List<RepositoryTreeNode<String>> remotes = new ArrayList<RepositoryTreeNode<String>>(); Repository rep = node.getRepository(); Set<String> configNames = rep.getConfig().getSubsections(RepositoriesView.REMOTE); for (String configName : configNames) { remotes.add(new RemoteNode(node, repo, configName)); } return remotes.toArray(); } case REPO: { List<RepositoryTreeNode<? extends Object>> nodeList = new ArrayList<RepositoryTreeNode<? extends Object>>(); nodeList.add(new BranchesNode(node, repo)); nodeList.add(new TagsNode(node, repo)); nodeList.add(new AdditionalRefsNode(node, repo)); nodeList.add(new WorkingDirNode(node, repo)); nodeList.add(new RemotesNode(node, repo)); return nodeList.toArray(); } case WORKINGDIR: { List<RepositoryTreeNode<File>> children = new ArrayList<RepositoryTreeNode<File>>(); if (node.getRepository().isBare()) return children.toArray(); File workingDir = repo.getWorkTree(); if (workingDir == null || !workingDir.exists()) return children.toArray(); File[] childFiles = workingDir.listFiles(); Arrays.sort(childFiles, new Comparator<File>() { public int compare(File o1, File o2) { if (o1.isDirectory()) { if (o2.isDirectory()) { return o1.compareTo(o2); } return -1; } else if (o2.isDirectory()) { return 1; } return o1.compareTo(o2); } }); for (File file : childFiles) { if (file.isDirectory()) { children.add(new FolderNode(node, repo, file)); } else { children.add(new FileNode(node, repo, file)); } } return children.toArray(); } case FOLDER: { List<RepositoryTreeNode<File>> children = new ArrayList<RepositoryTreeNode<File>>(); File parent = ((File) node.getObject()); File[] childFiles = parent.listFiles(); Arrays.sort(childFiles, new Comparator<File>() { public int compare(File o1, File o2) { if (o1.isDirectory()) { if (o2.isDirectory()) { return o1.compareTo(o2); } return -1; } else if (o2.isDirectory()) { return 1; } return o1.compareTo(o2); } }); for (File file : childFiles) { if (file.isDirectory()) { children.add(new FolderNode(node, repo, file)); } else { children.add(new FileNode(node, repo, file)); } } return children.toArray(); } case REMOTE: { List<RepositoryTreeNode<String>> children = new ArrayList<RepositoryTreeNode<String>>(); String remoteName = (String) node.getObject(); RemoteConfig rc; try { rc = new RemoteConfig(node.getRepository().getConfig(), remoteName); } catch (URISyntaxException e) { return handleException(e, node); } if (!rc.getURIs().isEmpty()) children.add(new FetchNode(node, node.getRepository(), rc.getURIs().get(0).toPrivateString())); int uriCount = rc.getPushURIs().size(); if (uriCount == 0 && !rc.getURIs().isEmpty()) uriCount++; // show push if either a fetch or push URI is specified and // at least one push specification if (uriCount > 0 && !rc.getPushRefSpecs().isEmpty()) { URIish firstUri; if (!rc.getPushURIs().isEmpty()) firstUri = rc.getPushURIs().get(0); else firstUri = rc.getURIs().get(0); if (uriCount == 1) children.add(new PushNode(node, node.getRepository(), firstUri.toPrivateString())); else children.add(new PushNode(node, node.getRepository(), firstUri.toPrivateString() + "...")); //$NON-NLS-1$ } return children.toArray(); } case FILE: // fall through case REF: // fall through case PUSH: // fall through case TAG: // fall through case FETCH: // fall through case ERROR: // fall through case ADDITIONALREF: return null; } return null; } private Object[] handleException(Exception e, RepositoryTreeNode parentNode) { Activator.handleError(e.getMessage(), e, false); // add a node indicating that there was an Exception String message = e.getMessage(); if (message == null) return new Object[] { new ErrorNode(parentNode, parentNode.getRepository(), UIText.RepositoriesViewContentProvider_ExceptionNodeText) }; else return new Object[] { new ErrorNode(parentNode, parentNode.getRepository(), message) }; } public Object getParent(Object element) { if (element instanceof RepositoryTreeNode) return ((RepositoryTreeNode) element).getParent(); return null; } public boolean hasChildren(Object element) { // for some of the nodes we can optimize this call RepositoryTreeNode node = (RepositoryTreeNode) element; Repository repo = node.getRepository(); switch (node.getType()) { case BRANCHES: return true; case REPO: return true; case ADDITIONALREFS: return true; case TAGS: try { return !repo.getRefDatabase().getRefs(Constants.R_TAGS).isEmpty(); } catch (IOException e) { return true; } case WORKINGDIR: if (node.getRepository().isBare()) return false; File workingDir = repo.getWorkTree(); if (workingDir == null || !workingDir.exists()) return false; return workingDir.listFiles().length > 0; default: Object[] children = getChildren(element); return children != null && children.length > 0; } } public void handleStateChange(State state, Object oldValue) { try { this.branchHierarchyMode = ((Boolean) state.getValue()).booleanValue(); } catch (Exception e) { Activator.handleError(e.getMessage(), e, false); } } }