| package org.eclipse.jst.jsf.common.internal.resource; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IPackageFragmentRoot; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jst.jsf.common.JSFCommonPlugin; |
| import org.eclipse.jst.jsf.common.internal.finder.AbstractMatcher.AlwaysMatcher; |
| import org.eclipse.jst.jsf.common.internal.finder.AbstractMatcher.IMatcher; |
| import org.eclipse.jst.jsf.common.internal.finder.VisitorMatcher; |
| import org.eclipse.jst.jsf.common.internal.finder.acceptor.ClasspathEntryJarMatchingAcceptor; |
| import org.eclipse.jst.jsf.common.internal.finder.acceptor.JarMatchingAcceptor; |
| import org.eclipse.jst.jsf.common.internal.resource.IClasspathLifecycleListener.ClasspathLifecycleEvent; |
| import org.eclipse.jst.jsf.common.internal.resource.IJarLocator.JarChangeEvent.Type; |
| |
| /** |
| * A default jar provider that traverses a project and returns all found jars on |
| * the classpath that a list of matcher criteria. |
| * |
| * @author cbateman |
| * |
| */ |
| public class DefaultJarLocator extends AbstractJarLocator |
| { |
| private static final String DISPLAY_NAME = "Default Jar Provider"; //$NON-NLS-1$ |
| private static final String ID = DefaultJarLocator.class.getCanonicalName(); |
| private final VisitorMatcher<IProject, ClasspathJarFile, String> _matcher; |
| private ClasspathEntryLifecycleListener _classpathEntryListener; |
| private final JavaCoreMediator _javaCoreMediator; |
| |
| /** |
| * @param javaCoreMediator |
| */ |
| public DefaultJarLocator(final JavaCoreMediator javaCoreMediator) |
| { |
| this(Collections.singletonList(new AlwaysMatcher()), javaCoreMediator); |
| } |
| |
| /** |
| * @param matchers |
| * @param javaCoreMediator |
| */ |
| public DefaultJarLocator(final List<? extends IMatcher> matchers, |
| final JavaCoreMediator javaCoreMediator) |
| { |
| super(ID, DISPLAY_NAME); |
| _matcher = new VisitorMatcher<IProject, ClasspathJarFile, String>(ID, |
| DISPLAY_NAME, new JarMatchingAcceptor(javaCoreMediator), |
| matchers); |
| _javaCoreMediator = javaCoreMediator; |
| _classpathEntryListener = new ClasspathEntryLifecycleListener( |
| _javaCoreMediator); |
| } |
| |
| @Override |
| public void start(final IProject project) |
| { |
| _classpathEntryListener.addLifecycleObject(project); |
| _classpathEntryListener.addListener(new IClasspathLifecycleListener() |
| { |
| public EventResult acceptEvent(final ClasspathLifecycleEvent event) |
| { |
| final IJavaElement affectedElement = event.getAffectedElement(); |
| final List<ClasspathJarFile> affectedJarFiles = new ArrayList<ClasspathJarFile>(); |
| if (isInteresting(project, affectedElement, event)) |
| { |
| Type jarEventType = null; |
| switch (event.getType()) |
| { |
| case ADDED: |
| jarEventType = Type.JAR_ADDED; |
| affectedJarFiles.addAll(getChangedJars((IPackageFragmentRoot) affectedElement)); |
| break; |
| case REMOVED: |
| jarEventType = Type.JAR_REMOVED; |
| affectedJarFiles.addAll(getChangedJars((IPackageFragmentRoot) affectedElement)); |
| break; |
| case REMOVED_DELTA: |
| jarEventType = Type.JAR_REMOVED; |
| IResource res = event.getAffectedResource(); |
| if (res.getType() == IResource.FILE && |
| "jar".equals(res.getFileExtension())) //$NON-NLS-1$ |
| { |
| IPath path = res.getLocation(); |
| if (path != null) |
| { |
| affectedJarFiles.add(new ClasspathJarFile(project, path)); |
| } |
| } |
| break; |
| } |
| |
| if (jarEventType != null && !affectedJarFiles.isEmpty()) |
| { |
| for (final ClasspathJarFile changedJar : affectedJarFiles) |
| { |
| fireChangeEvent(new JarChangeEvent( |
| DefaultJarLocator.this, jarEventType, |
| changedJar)); |
| } |
| } |
| } |
| return EventResult.getDefaultEventResult(); |
| } |
| |
| private Collection<? extends ClasspathJarFile> getChangedJars( |
| final IPackageFragmentRoot affectedElement) |
| { |
| try |
| { |
| return new VisitorMatcher<IPackageFragmentRoot, ClasspathJarFile, String>( |
| "", "", new ClasspathEntryJarMatchingAcceptor(project), //$NON-NLS-1$ //$NON-NLS-2$ |
| Collections.singletonList(new AlwaysMatcher())) |
| .find(affectedElement); |
| } catch (final JavaModelException e) |
| { |
| return Collections.EMPTY_LIST; |
| } catch (final Exception e) |
| { |
| return Collections.EMPTY_LIST; |
| } |
| } |
| }); |
| super.start(project); |
| } |
| |
| private boolean isInteresting(final IProject project, |
| final IJavaElement affectedElement, final ClasspathLifecycleEvent event) |
| { |
| return |
| // first filter out events that aren't related to the project we care about. |
| (affectedElement != null |
| && affectedElement.getJavaProject() != null |
| && project |
| .equals(affectedElement.getJavaProject().getProject())) |
| // then filter down to only events impacting frag roots |
| // or jar file deletions |
| && (affectedElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT_ROOT |
| || (affectedElement.getElementType() == IJavaElement.JAVA_PROJECT |
| && event.getAffectedResource() != null |
| && event.getType() == ClasspathLifecycleEvent.Type.REMOVED_DELTA)); |
| } |
| |
| @Override |
| public void stop() |
| { |
| _classpathEntryListener.dispose(); |
| super.stop(); |
| } |
| |
| @Override |
| protected Collection<? extends ClasspathJarFile> doLocate( |
| final IProject project) |
| { |
| try |
| { |
| return _matcher.find(project); |
| } catch (final Exception e) |
| { |
| JSFCommonPlugin |
| .log(e, "While getting jars for project: " + project); //$NON-NLS-1$ |
| return getNoResult(); |
| } |
| } |
| } |