Skip to main content
summaryrefslogtreecommitdiffstats
blob: 4f31cc1782a3c237c43187efdfdc3362081daa85 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
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();
        }
    }
}

Back to the top