/******************************************************************************* * Copyright (c) 2006, 2010 Spring IDE Developers * 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: * Spring IDE Developers - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.beans.ui.properties; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IContainer; 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.IStorage; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaElementDelta; import org.eclipse.jdt.core.IJavaModel; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IParent; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.internal.core.JarEntryDirectory; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; import org.springframework.ide.eclipse.core.io.ZipEntryStorage; import org.springframework.ide.eclipse.core.java.JdtUtils; /** * This content provider is used to display a tree of non-java resources. * @author Torsten Juergeleit * @author Christian Dupuis */ @SuppressWarnings("restriction") public class NonJavaResourceContentProvider implements ITreeContentProvider { public static final Object[] NO_CHILDREN = new Object[0]; private static final Path JVM_CLASSPATH_CONTAINER = new Path( "org.eclipse.jdt.launching.JRE_CONTAINER"); public void dispose() { } public Object[] getChildren(Object element) { if (!exists(element)) { return NO_CHILDREN; } try { if (element instanceof IProject) { IProject project = (IProject) element; if (JdtUtils.isJavaProject(project)) { element = JavaCore.create(project); } } if (element instanceof IJavaProject) { return getPackageFragmentRoots((IJavaProject) element); } if (element instanceof IProject) { return getResources((IProject) element); } if (element instanceof IPackageFragmentRoot) { return getPackageFragments((IPackageFragmentRoot) element); } if (element instanceof IPackageFragment) { return getPackageContents((IPackageFragment) element); } if (element instanceof IFolder) { return getResources((IFolder) element); } if (element instanceof JarEntryDirectory) { return getResources((JarEntryDirectory) element); } } catch (JavaModelException e) { return NO_CHILDREN; } return NO_CHILDREN; } public Object[] getElements(Object parent) { return getChildren(parent); } public Object getParent(Object element) { if (!exists(element)) { return null; } return internalGetParent(element); } public boolean hasChildren(Object element) { if (element instanceof IProject) { IProject project = (IProject) element; if (!project.isOpen()) { return false; } } if (element instanceof IJavaProject) { IJavaProject javaProject = (IJavaProject) element; if (!javaProject.getProject().isOpen()) { return false; } } if (element instanceof IParent) { try { // when we have Java children return true, else we fetch all // the children if (((IParent) element).hasChildren()) { return true; } } catch (JavaModelException e) { return true; } } Object[] children = getChildren(element); return (children != null) && children.length > 0; } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } private Object[] getNonJavaResources(IPackageFragment fragment) throws JavaModelException { Object[] nonJavaResources = fragment.getNonJavaResources(); IPackageFragmentRoot root = (IPackageFragmentRoot) fragment .getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); if (root != null && root.getKind() == IPackageFragmentRoot.K_BINARY) { for (int i = 0; i < nonJavaResources.length; i++) { Object resource = nonJavaResources[i]; if (resource instanceof IFile) { nonJavaResources[i] = resource; } else if (resource instanceof IStorage && root.getResource() instanceof IFile) { IStorage storage = (IStorage) resource; nonJavaResources[i] = new ZipEntryStorage((IFile) root.getResource(), storage .getFullPath().toString()); } } } return nonJavaResources; } private Object[] getNonJavaResources(IPackageFragmentRoot root) throws JavaModelException { Object[] nonJavaResources = root.getNonJavaResources(); // Replace JAR entries with our own wrapper if (root.getKind() == IPackageFragmentRoot.K_BINARY && root.getResource() instanceof IFile) { for (int i = 0; i < nonJavaResources.length; i++) { Object resource = nonJavaResources[i]; if (resource instanceof IStorage) { IStorage storage = (IStorage) resource; nonJavaResources[i] = new ZipEntryStorage((IFile) root.getResource(), storage .getFullPath().toString()); } } } return nonJavaResources; } private Object[] getPackageContents(IPackageFragment fragment) throws JavaModelException { return getNonJavaResources(fragment); } private Object[] getPackageFragments(IPackageFragmentRoot root) throws JavaModelException { Object[] fragments = root.getChildren(); Object[] nonJavaResources = getNonJavaResources(root); if (nonJavaResources == null) { return fragments; } return concatenate(fragments, nonJavaResources); } private Object[] getResources(IContainer container) { try { IResource[] members = container.members(); IJavaProject javaProject = JavaCore.create(container.getProject()); if (javaProject == null || !javaProject.exists()) { return members; } boolean isFolderOnClasspath = javaProject.isOnClasspath(container); List<Object> nonJavaResources = new ArrayList<Object>(); // Can be on classpath but as a member of non-java resource folder for (IResource member : members) { // A resource can also be a java element in the case of // exclusion and inclusion filters. We therefore exclude Java // elements from the list of non-Java resources. if (isFolderOnClasspath) { if (javaProject.findPackageFragmentRoot(member.getFullPath()) == null) { nonJavaResources.add(member); } } else if (!javaProject.isOnClasspath(member)) { nonJavaResources.add(member); } } return nonJavaResources.toArray(); } catch (CoreException e) { return NO_CHILDREN; } } private Object[] getResources(JarEntryDirectory element) { return element.getChildren(); } protected boolean exists(Object element) { if (element == null) { return false; } if (element instanceof IResource) { return ((IResource) element).exists(); } if (element instanceof IJavaElement) { return ((IJavaElement) element).exists(); } return true; } protected Object[] getJavaProjects(IJavaModel model) throws JavaModelException { return model.getJavaProjects(); } protected Object[] getPackageFragmentRoots(IJavaProject project) throws JavaModelException { if (!project.getProject().isOpen()) { return NO_CHILDREN; } List<IJavaElement> list = new ArrayList<IJavaElement>(); for (IPackageFragmentRoot root : project.getPackageFragmentRoots()) { if (!JVM_CLASSPATH_CONTAINER.isPrefixOf(root.getRawClasspathEntry().getPath())) { if (isProjectPackageFragmentRoot(root)) { for (IJavaElement element : root.getChildren()) { list.add(element); } } else if (hasChildren(root)) { list.add(root); } } } return concatenate(list.toArray(), project.getNonJavaResources()); } protected Object internalGetParent(Object element) { // try to map resources to the containing package fragment if (element instanceof IResource) { IResource parent = ((IResource) element).getParent(); IJavaElement jParent = JavaCore.create(parent); // http://bugs.eclipse.org/bugs/show_bug.cgi?id=31374 if (jParent != null && jParent.exists()) { return jParent; } return parent; } else if (element instanceof IJavaElement) { IJavaElement parent = ((IJavaElement) element).getParent(); // For package fragments that are contained in a project package // fragment we have to skip the package fragment root as the parent. if (element instanceof IPackageFragment) { return skipProjectPackageFragmentRoot((IPackageFragmentRoot) parent); } return parent; } return null; } protected boolean isClasspathChange(IJavaElementDelta delta) { // need to test the flags only for package fragment roots if (delta.getElement().getElementType() != IJavaElement.PACKAGE_FRAGMENT_ROOT) { return false; } int flags = delta.getFlags(); return (delta.getKind() == IJavaElementDelta.CHANGED && ((flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) != 0) || ((flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) || ((flags & IJavaElementDelta.F_REORDER) != 0)); } protected boolean isInternalLibrary(IJavaProject project, IPackageFragmentRoot root) { if (root.isArchive()) { IResource resource = root.getResource(); if (resource != null) { IProject jarProject = resource.getProject(); IProject container = root.getJavaProject().getProject(); return container.equals(jarProject); } return false; } return true; } protected boolean isPackageFragmentEmpty(IJavaElement element) throws JavaModelException { if (element instanceof IPackageFragment) { IPackageFragment fragment = (IPackageFragment) element; if (fragment.exists() && !(fragment.hasChildren() || fragment.getNonJavaResources().length > 0) && fragment.hasSubpackages()) { return true; } } return false; } protected boolean isProjectPackageFragmentRoot(IPackageFragmentRoot root) { IResource resource = root.getResource(); return (resource instanceof IProject); } protected Object skipProjectPackageFragmentRoot(IPackageFragmentRoot root) { if (isProjectPackageFragmentRoot(root)) { return root.getParent(); } return root; } protected static Object[] concatenate(Object[] a1, Object[] a2) { int a1Len = a1.length; int a2Len = a2.length; Object[] res = new Object[a1Len + a2Len]; System.arraycopy(a1, 0, res, 0, a1Len); System.arraycopy(a2, 0, res, a1Len, a2Len); return res; } }