KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > externaltools > internal > model > ExternalToolBuilder


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
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  * IBM Corporation - initial API and implementation
10  * Matthew Conway - Bug 175186
11  *******************************************************************************/

12 package org.eclipse.ui.externaltools.internal.model;
13
14
15 import java.util.Map JavaDoc;
16
17 import org.eclipse.core.resources.ICommand;
18 import org.eclipse.core.resources.IFile;
19 import org.eclipse.core.resources.IProject;
20 import org.eclipse.core.resources.IProjectDescription;
21 import org.eclipse.core.resources.IResource;
22 import org.eclipse.core.resources.IResourceDelta;
23 import org.eclipse.core.resources.IResourceDeltaVisitor;
24 import org.eclipse.core.resources.IncrementalProjectBuilder;
25 import org.eclipse.core.runtime.CoreException;
26 import org.eclipse.core.runtime.IPath;
27 import org.eclipse.core.runtime.IProgressMonitor;
28 import org.eclipse.debug.core.ILaunchConfiguration;
29 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
30 import org.eclipse.debug.core.ILaunchManager;
31 import org.eclipse.osgi.util.NLS;
32 import org.eclipse.ui.externaltools.internal.launchConfigurations.ExternalToolsUtil;
33 import org.eclipse.ui.externaltools.internal.registry.ExternalToolMigration;
34 import org.osgi.framework.Bundle;
35
36 /**
37  * This project builder implementation will run an external tool during the
38  * build process.
39  */

40 public final class ExternalToolBuilder extends IncrementalProjectBuilder {
41     private final class IgnoreTeamPrivateChanges implements IResourceDeltaVisitor {
42         private boolean[] fTrueChange;
43         private IgnoreTeamPrivateChanges(boolean[] trueChange) {
44             super();
45             fTrueChange= trueChange;
46         }
47         public boolean visit(IResourceDelta visitDelta) throws CoreException {
48             IResource resource= visitDelta.getResource();
49             if (resource instanceof IFile) {
50                 fTrueChange[0]= true;
51                 return false;
52             }
53             return true;
54         }
55     }
56
57     public static final String JavaDoc ID = "org.eclipse.ui.externaltools.ExternalToolBuilder"; //$NON-NLS-1$;
58

59     private static String JavaDoc buildType = IExternalToolConstants.BUILD_TYPE_NONE;
60     
61     private static IProject buildProject= null;
62     private static IResourceDelta buildDelta= null;
63     
64     /* (non-Javadoc)
65      * @see org.eclipse.core.internal.events.InternalBuilder#build(int, java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
66      */

67     protected IProject[] build(int kind, Map JavaDoc args, IProgressMonitor monitor) throws CoreException {
68         if (ExternalToolsPlugin.getDefault().getBundle().getState() != Bundle.ACTIVE) {
69             return null;
70         }
71         
72         ILaunchConfiguration config= BuilderUtils.configFromBuildCommandArgs(getProject(), args, new String JavaDoc[1]);
73         if (config == null) {
74             throw ExternalToolsPlugin.newError(ExternalToolsModelMessages.ExternalToolBuilder_0, null);
75         }
76         IProject[] projectsWithinScope= null;
77         IResource[] resources = ExternalToolsUtil.getResourcesForBuildScope(config);
78         if (resources != null) {
79             projectsWithinScope= new IProject[resources.length];
80             for (int i = 0; i < resources.length; i++) {
81                 projectsWithinScope[i]= resources[i].getProject();
82             }
83         }
84         boolean kindCompatible= commandConfiguredForKind(config, kind);
85         if (kindCompatible && configEnabled(config)) {
86             doBuildBasedOnScope(resources, kind, config, monitor);
87         }
88         
89         return projectsWithinScope;
90     }
91
92     private boolean commandConfiguredForKind(ILaunchConfiguration config, int kind) {
93         try {
94             if (!(config.getAttribute(IExternalToolConstants.ATTR_TRIGGERS_CONFIGURED, false))) {
95                 ICommand command= getCommand();
96                 //adapt the builder command to make use of the 3.1 support for setting command build kinds
97
//this will only happen once for builder/command defined before the support existed
98
BuilderUtils.configureTriggers(config, command);
99                 IProjectDescription desc= getProject().getDescription();
100                 ICommand[] commands= desc.getBuildSpec();
101                 int index= getBuilderCommandIndex(commands, command);
102                 if (index != -1) {
103                     commands[index]= command;
104                     desc.setBuildSpec(commands);
105                     getProject().setDescription(desc, null);
106                     ILaunchConfigurationWorkingCopy copy= config.getWorkingCopy();
107                     copy.setAttribute(IExternalToolConstants.ATTR_TRIGGERS_CONFIGURED, true);
108                     copy.doSave();
109                 }
110                 return command.isBuilding(kind);
111             }
112         } catch (CoreException e) {
113            ExternalToolsPlugin.getDefault().log(e);
114            return true;
115         }
116         return true;
117     }
118     
119     private int getBuilderCommandIndex(ICommand[] buildSpec, ICommand command) {
120         Map JavaDoc commandArgs= command.getArguments();
121         if (commandArgs == null) {
122             return -1;
123         }
124         String JavaDoc handle= (String JavaDoc) commandArgs.get(BuilderUtils.LAUNCH_CONFIG_HANDLE);
125         if (handle == null) {
126             return -1;
127         }
128         for (int i = 0; i < buildSpec.length; ++i) {
129             ICommand buildSpecCommand= buildSpec[i];
130             if (ID.equals(buildSpecCommand.getBuilderName())) {
131                 Map JavaDoc buildSpecArgs= buildSpecCommand.getArguments();
132                 if (buildSpecArgs != null) {
133                     String JavaDoc buildSpecHandle= (String JavaDoc) buildSpecArgs.get(BuilderUtils.LAUNCH_CONFIG_HANDLE);
134                     if (handle.equals(buildSpecHandle)) {
135                         return i;
136                     }
137                 }
138             }
139         }
140         return -1;
141     }
142
143     /**
144      * Returns whether the given builder config is enabled or not.
145      *
146      * @param config the config to examine
147      * @return whether the config is enabled
148      */

149     private boolean configEnabled(ILaunchConfiguration config) {
150         try {
151             return ExternalToolsUtil.isBuilderEnabled(config);
152         } catch (CoreException e) {
153             ExternalToolsPlugin.getDefault().log(e);
154         }
155         return true;
156     }
157
158     private void doBuildBasedOnScope(IResource[] resources, int kind, ILaunchConfiguration config, IProgressMonitor monitor) throws CoreException {
159         boolean buildForChange = true;
160         if (kind != FULL_BUILD) { //scope not applied for full builds
161
if (resources != null && resources.length > 0) {
162                 buildForChange = buildScopeIndicatesBuild(resources);
163             }
164         }
165
166         if (buildForChange) {
167             launchBuild(kind, config, monitor);
168         }
169     }
170     
171     private void launchBuild(int kind, ILaunchConfiguration config, IProgressMonitor monitor) throws CoreException {
172         monitor.subTask(NLS.bind(ExternalToolsModelMessages.ExternalToolBuilder_Running__0_____1, new String JavaDoc[] { config.getName()}));
173         buildStarted(kind);
174         // The default value for "launch in background" is true in debug core. If
175
// the user doesn't go through the UI, the new attribute won't be set. This means
176
// that existing Ant builders will try to run in the background (and likely conflict with
177
// each other) without migration.
178
config= ExternalToolMigration.migrateRunInBackground(config);
179         config.launch(ILaunchManager.RUN_MODE, monitor);
180         buildEnded();
181     }
182
183     /**
184      * Returns the build type being performed if the
185      * external tool is being run as a project builder.
186      *
187      * @return one of the <code>IExternalToolConstants.BUILD_TYPE_*</code> constants.
188      */

189     public static String JavaDoc getBuildType() {
190         return buildType;
191     }
192     
193     /**
194      * Returns the project that is being built and has triggered the current external
195      * tool builder. <code>null</code> is returned if no build is currently occurring.
196      *
197      * @return project being built or <code>null</code>.
198      */

199     public static IProject getBuildProject() {
200         return buildProject;
201     }
202
203     /**
204      * Returns the <code>IResourceDelta</code> that is being built and has triggered the current external
205      * tool builder. <code>null</code> is returned if no build is currently occurring.
206      *
207      * @return resource delta for the build or <code>null</code>
208      */

209     public static IResourceDelta getBuildDelta() {
210         return buildDelta;
211     }
212     
213     /**
214      * Stores the currently active build kind and build project when a build begins
215      * @param buildKind
216      */

217     private void buildStarted(int buildKind) {
218         switch (buildKind) {
219             case IncrementalProjectBuilder.INCREMENTAL_BUILD :
220                 buildType = IExternalToolConstants.BUILD_TYPE_INCREMENTAL;
221                 buildDelta = getDelta(getProject());
222                 break;
223             case IncrementalProjectBuilder.FULL_BUILD :
224                 buildType = IExternalToolConstants.BUILD_TYPE_FULL;
225                 break;
226             case IncrementalProjectBuilder.AUTO_BUILD :
227                 buildType = IExternalToolConstants.BUILD_TYPE_AUTO;
228                 buildDelta = getDelta(getProject());
229                 break;
230             case IncrementalProjectBuilder.CLEAN_BUILD :
231                 buildType = IExternalToolConstants.BUILD_TYPE_CLEAN;
232                 break;
233             default :
234                 buildType = IExternalToolConstants.BUILD_TYPE_NONE;
235                 break;
236         }
237         buildProject= getProject();
238     }
239     
240     /**
241      * Clears the current build kind, build project and build delta when a build finishes.
242      */

243     private void buildEnded() {
244         buildType= IExternalToolConstants.BUILD_TYPE_NONE;
245         buildProject= null;
246         buildDelta= null;
247     }
248     
249     private boolean buildScopeIndicatesBuild(IResource[] resources) {
250         for (int i = 0; i < resources.length; i++) {
251             IResourceDelta delta = getDelta(resources[i].getProject());
252             if (delta == null) {
253                 //project just added to the workspace..no previous build tree
254
return true;
255             }
256             IPath path= resources[i].getProjectRelativePath();
257             IResourceDelta change= delta.findMember(path);
258             if (change != null) {
259                 final boolean[] trueChange= new boolean[1];
260                 trueChange[0]= false;
261                 try {
262                     change.accept(new IgnoreTeamPrivateChanges(trueChange));
263                 } catch (CoreException e) {
264                     ExternalToolsPlugin.getDefault().log("Internal error resolving changed resources during build", e); //$NON-NLS-1$
265
}
266                 
267                 return trueChange[0]; //filtered out team private changes
268
}
269         }
270         return false;
271     }
272     
273     protected void clean(IProgressMonitor monitor) throws CoreException {
274         ICommand command= getCommand();
275         ILaunchConfiguration config= BuilderUtils.configFromBuildCommandArgs(getProject(), command.getArguments(), new String JavaDoc[1]);
276         if (!configEnabled(config)) {
277             return;
278         }
279         
280         if ((!config.getAttribute(IExternalToolConstants.ATTR_TRIGGERS_CONFIGURED, false))) {
281             //old behavior
282
super.clean(monitor);
283             return;
284         }
285     
286         launchBuild(IncrementalProjectBuilder.CLEAN_BUILD, config, monitor);
287     }
288 }
Popular Tags