KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > apt > core > internal > generatedfile > GeneratedResourceChangeListener


1 /*******************************************************************************
2  * Copyright (c) 2005, 2007 BEA Systems, Inc.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * mkaufman@bea.com - initial API and implementation
10  *
11  *******************************************************************************/

12
13 package org.eclipse.jdt.apt.core.internal.generatedfile;
14
15 import java.util.Collections JavaDoc;
16 import java.util.HashSet JavaDoc;
17 import java.util.Set JavaDoc;
18
19 import org.eclipse.core.resources.IFile;
20 import org.eclipse.core.resources.IFolder;
21 import org.eclipse.core.resources.IProject;
22 import org.eclipse.core.resources.IResource;
23 import org.eclipse.core.resources.IResourceChangeEvent;
24 import org.eclipse.core.resources.IResourceChangeListener;
25 import org.eclipse.core.resources.IResourceDelta;
26 import org.eclipse.core.resources.IResourceDeltaVisitor;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.jdt.apt.core.internal.AptPlugin;
29 import org.eclipse.jdt.apt.core.internal.AptProject;
30 import org.eclipse.jdt.apt.core.util.AptConfig;
31 import org.eclipse.jdt.core.IJavaProject;
32 import org.eclipse.jdt.core.JavaCore;
33
34 /**
35  * A jdt.core pre-process resource change listener that manages generated resources.
36  * <p>
37  *
38  * Note that this is both a pre-build listener and a post-change listener,
39  * because there is a bug in the resource change event notification in the platform:
40  * sometimes they fail to send out deletion notifications for files in pre-build,
41  * but they do send them out in post-change.
42  */

43 public class GeneratedResourceChangeListener implements IResourceChangeListener
44 {
45     // Synchronized collection, as post-change notifications could come in
46
// simultaneously. Note that pre-build will not though, as it holds the
47
// workspace lock
48
private final Set JavaDoc<IResource> deletedResources =
49         Collections.synchronizedSet(new HashSet JavaDoc<IResource>());
50     
51     public GeneratedResourceChangeListener(){}
52     
53     public void resourceChanged(IResourceChangeEvent event)
54     {
55         if ( event.getType() == IResourceChangeEvent.PRE_CLOSE )
56         {
57             IProject p = (IProject)event.getResource();
58             if( AptPlugin.DEBUG_GFM )
59                 AptPlugin.trace(
60                         "generated resource change listener got a pre-close event: project = " + p.getName()); //$NON-NLS-1$
61
IJavaProject jp = JavaCore.create(p);
62             AptPlugin.getAptProject(jp).projectClosed();
63         }
64         else if ( event.getType() == IResourceChangeEvent.PRE_DELETE )
65         {
66             // TODO: need to update projectDeleted() to delete the generated_src folder
67
// in an async thread. The resource tree is locked here.
68
IProject p = (IProject)event.getResource();
69             if( AptPlugin.DEBUG_GFM )
70                 AptPlugin.trace(
71                         "generated resource change listener got a pre-delete event: project = " + p.getName()); //$NON-NLS-1$
72
IJavaProject jp = JavaCore.create(p);
73             AptPlugin.getAptProject(jp).projectDeleted();
74             AptPlugin.deleteAptProject(jp);
75         }
76         else if ( event.getType() == IResourceChangeEvent.PRE_BUILD )
77         {
78             try
79             {
80                 if( AptPlugin.DEBUG_GFM )
81                     AptPlugin.trace("generated resource change listener got a pre-build event"); //$NON-NLS-1$
82

83                 final PreBuildVisitor pbv = new PreBuildVisitor();
84                 
85                 // First we need to handle previously deleted resources (from the post-change event),
86
// because we could not perform file i/o during that event
87
for (IResource resource : deletedResources) {
88                     pbv.handleDeletion(resource);
89                 }
90                 
91                 event.getDelta().accept( pbv );
92                 addGeneratedSrcFolderTo(pbv.getProjectsThatNeedGenSrcFolder());
93                 
94                 // Now clear the set of deleted resources,
95
// as we don't want to re-handle them
96
deletedResources.clear();
97             }
98             catch ( CoreException ce )
99             {
100                 AptPlugin.log(ce, "Error during pre-build resource change"); //$NON-NLS-1$
101
}
102         }
103         else if (event.getType() == IResourceChangeEvent.POST_CHANGE) {
104             if( AptPlugin.DEBUG_GFM )
105                 AptPlugin.trace(
106                         "generated resource change listener got a post-change event"); //$NON-NLS-1$
107
PostChangeVisitor pcv = new PostChangeVisitor();
108             try {
109                 event.getDelta().accept(pcv);
110             }
111             catch (CoreException ce) {
112                 AptPlugin.log(ce, "Error during post-change resource event"); //$NON-NLS-1$
113
}
114         }
115     }
116     
117     private void addGeneratedSrcFolderTo(final Set JavaDoc<IProject> projs ){
118         
119         for(IProject proj : projs ){
120             final IJavaProject javaProj = JavaCore.create(proj);
121             if(javaProj.getProject().isOpen() && AptConfig.isEnabled(javaProj)){
122                 final GeneratedSourceFolderManager gsfm = AptPlugin.getAptProject(javaProj).getGeneratedSourceFolderManager();
123                 gsfm.ensureFolderExists();
124             }
125         }
126
127     }
128     
129     /**
130      * We need a post-change visitor, as there is a bug in the platform for
131      * resource change notification -- some items will be reported *only* in the post-change event,
132      * so we keep track of them here and handle them in the pre-build
133      */

134     private class PostChangeVisitor implements IResourceDeltaVisitor {
135
136         public boolean visit(IResourceDelta delta) throws CoreException {
137             if( delta.getKind() == IResourceDelta.REMOVED ){
138                 if (AptPlugin.DEBUG_GFM) {
139                     AptPlugin.trace("generated resource post-change listener adding to deletedResources:" + //$NON-NLS-1$
140
delta.getResource().getName());
141                 }
142                 deletedResources.add(delta.getResource());
143             }
144             
145             return true;
146         }
147         
148     }
149
150     private class PreBuildVisitor implements IResourceDeltaVisitor
151     {
152         // projects that we need to add the generated source folder to.
153
private final Set JavaDoc<IProject> _addGenFolderTo = new HashSet JavaDoc<IProject>();
154         // any projects that is closed or about to be deleted
155
private final Set JavaDoc<IProject> _removedProjects = new HashSet JavaDoc<IProject>();
156         public boolean visit(IResourceDelta delta) throws CoreException
157         {
158             IResource r = delta.getResource();
159             IProject project = r.getProject();
160             
161             if ( project == null )
162                 return true;
163             
164             if( delta.getKind() == IResourceDelta.REMOVED ){
165                 if (!deletedResources.contains(r)) {
166                     handleDeletion(r);
167                 }
168             }
169             else if( r instanceof IProject ){
170                 final IProject proj = (IProject)delta.getResource();
171                 if( canUpdate(proj) ){
172                     _addGenFolderTo.add(proj);
173                 }
174                 else
175                     _removedProjects.add(proj);
176             }
177
178             return true;
179         }
180         
181         private void handleDeletion(IResource resource) throws CoreException {
182             if (AptPlugin.DEBUG_GFM) {
183                 AptPlugin.trace("handleDeletion: resource = " + resource.getName()); //$NON-NLS-1$
184
}
185             IProject project = resource.getProject();
186             final IJavaProject javaProj = JavaCore.create(project);
187             final AptProject aptProj = AptPlugin.getAptProject(javaProj);
188             if( resource instanceof IFile ){
189                 final GeneratedFileManager gfm = aptProj.getGeneratedFileManager();
190                 IFile f = (IFile)resource;
191                 gfm.fileDeleted(f);
192             }
193             else if( resource instanceof IFolder ){
194                 final GeneratedSourceFolderManager gsfm = aptProj.getGeneratedSourceFolderManager();
195                 IFolder f = (IFolder) resource;
196                 if ( gsfm.isGeneratedSourceFolder( f ) ){
197                     gsfm.folderDeleted();
198                     // all deletion occurs before any add (adding the generated source directory)
199
if( !_removedProjects.contains(project) ){
200                         _addGenFolderTo.add(project);
201                     }
202                     // if the project is already closed or in the process of being
203
// deleted, will ignore this deletion since we cannot correct
204
// the classpath anyways.
205
}
206             }
207             else if( resource instanceof IProject ){
208                 _removedProjects.add((IProject)resource);
209             }
210         }
211         
212         Set JavaDoc<IProject> getProjectsThatNeedGenSrcFolder(){
213             _addGenFolderTo.removeAll(_removedProjects);
214             return _addGenFolderTo;
215         }
216         
217         private boolean canUpdate(IProject proj)
218             throws CoreException
219         {
220             return proj.isOpen() && proj.exists() && proj.hasNature(JavaCore.NATURE_ID);
221         }
222     }
223 }
224
Popular Tags