|
1 /* |
|
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 package com.nokia.s60tools.appdep.core; |
|
20 |
|
21 import java.io.File; |
|
22 import java.io.IOException; |
|
23 import java.util.ArrayList; |
|
24 import java.util.Vector; |
|
25 |
|
26 import org.eclipse.core.runtime.jobs.Job; |
|
27 |
|
28 import com.nokia.s60tools.appdep.common.ProductInfoRegistry; |
|
29 import com.nokia.s60tools.appdep.core.data.CacheDataConstants; |
|
30 import com.nokia.s60tools.appdep.exceptions.InvalidCmdLineToolSettingException; |
|
31 import com.nokia.s60tools.appdep.resources.Messages; |
|
32 import com.nokia.s60tools.appdep.util.AppDepConsole; |
|
33 import com.nokia.s60tools.util.cmdline.CmdLineCommandExecutorFactory; |
|
34 import com.nokia.s60tools.util.cmdline.ICmdLineCommandExecutor; |
|
35 import com.nokia.s60tools.util.cmdline.ICmdLineCommandExecutorObserver; |
|
36 import com.nokia.s60tools.util.cmdline.ICustomLineReader; |
|
37 import com.nokia.s60tools.util.cmdline.UnsupportedOSException; |
|
38 import com.nokia.s60tools.util.console.IConsolePrintUtility; |
|
39 import com.nokia.s60tools.util.debug.DbgUtility; |
|
40 import com.nokia.s60tools.util.resource.FileUtils; |
|
41 |
|
42 |
|
43 /** |
|
44 * The purpose of this class is offer as a facade for |
|
45 * the appdep core services (command line tool). |
|
46 */ |
|
47 public class AppDepCoreFacade implements ICmdLineCommandExecutorObserver { |
|
48 |
|
49 private String options = null; |
|
50 private String commands = null; |
|
51 |
|
52 private ICmdLineCommandExecutor cmdLineExecutor = null; |
|
53 private AppDepSettings settings = null; |
|
54 private ICmdLineCommandExecutorObserver observer = null; |
|
55 private Job currentJobContext = null; |
|
56 |
|
57 /** |
|
58 * Separator character used between targets platforms when generating |
|
59 * cache for multiple targets in single command. |
|
60 */ |
|
61 private static final String TARGET_SEPARATOR = "+"; //$NON-NLS-1$ |
|
62 |
|
63 /** |
|
64 * folder where SIS cache files is located under cache base dir |
|
65 */ |
|
66 private static final String SIS_PATH = "sis";//$NON-NLS-1$ |
|
67 |
|
68 /** |
|
69 * Stroring list of targets that is currentlu selected |
|
70 */ |
|
71 private ITargetPlatform[] currentlySelectedTargets = null; |
|
72 |
|
73 /** |
|
74 * This flag is <code>true</code> when the settings should to be |
|
75 * checked from cache generation options instead from default settings. |
|
76 */ |
|
77 private boolean checkFromCacheGenerOpts = false; |
|
78 |
|
79 public AppDepCoreFacade(AppDepSettings settings, |
|
80 ICmdLineCommandExecutorObserver observer |
|
81 ) throws UnsupportedOSException{ |
|
82 |
|
83 // Storing the client observer |
|
84 this.observer = observer; |
|
85 // And passing ourselves as real observers |
|
86 cmdLineExecutor = CmdLineCommandExecutorFactory.CreateOsDependentCommandLineExecutor(this, AppDepConsole.getInstance()); |
|
87 this.settings = settings; |
|
88 |
|
89 options = new String(""); //$NON-NLS-1$ |
|
90 commands = new String(""); //$NON-NLS-1$ |
|
91 } |
|
92 |
|
93 /** |
|
94 * Constructs command line tool parameters based on the current settings and given arguments. |
|
95 * @param targetPlatformIdentifiers Id of the used target platform(s) separated |
|
96 * with TARGET_SEPARATOR character. |
|
97 * @return Parameters for the commoand. |
|
98 * @throws InvalidCmdLineToolSettingException |
|
99 */ |
|
100 private String prepareParameters(String targetPlatformIdentifiers) throws InvalidCmdLineToolSettingException{ |
|
101 |
|
102 CacheGenerationOptions cacheGenerOpts = settings.getCacheGenerOptions(); |
|
103 String toolchainNameStr = null; |
|
104 String parameters = new String(""); //$NON-NLS-1$ |
|
105 |
|
106 if(checkFromCacheGenerOpts && cacheGenerOptionsAreSet()){ |
|
107 toolchainNameStr = cacheGenerOpts.getUsedToolchain().getToolchainName(); |
|
108 } |
|
109 else{ |
|
110 toolchainNameStr = settings.getCurrentlyUsedToolChain().getToolchainName(); |
|
111 } |
|
112 |
|
113 if( toolchainNameStr.compareToIgnoreCase( "RVCT" ) == 0 ){ //$NON-NLS-1$ |
|
114 |
|
115 // An example RVCT command line |
|
116 // set CMD_LINE=appdep RVCT -cfilt %CFILT_DIR%\cfilt.exe |
|
117 // -tools %RVCT_TOOLS% -cache %CACHE_DIR% -release %SDK_ROOT% |
|
118 // -targets ARMV5 %OPT% %COMMAND% %COMPONENT% |
|
119 |
|
120 parameters = "-tools " + "\"" + settings.getRvctToolsDir() + "\"" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
|
121 + " -cfilt " + "\"" + settings.getCfiltProgramPathName() + "\"" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
|
122 + " -cache " + "\"" + settings.getCacheBaseDirForCurrentlyUsedSdk() + "\"" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
|
123 + " -release " + "\"" + settings.getSdkRootDir() + "\"" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
|
124 + " -targets " + targetPlatformIdentifiers; //$NON-NLS-1$ |
|
125 } |
|
126 else if( toolchainNameStr.compareToIgnoreCase( "GCCE" ) == 0 ){ //$NON-NLS-1$ |
|
127 |
|
128 // An example GCCE command line |
|
129 // appdep GCCE -tools %GCCE_TOOLS% -cache %CACHE_DIR% -release %SDK_ROOT% |
|
130 // -targets GCCE %OPT% %COMMAND% %COMPONENT% |
|
131 |
|
132 parameters = "-tools " + "\"" + settings.getGcceToolsDir() + "\"" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
|
133 + " -cache " + "\"" + settings.getCacheBaseDirForCurrentlyUsedSdk() + "\"" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
|
134 + " -release " + "\"" + settings.getSdkRootDir() + "\"" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
|
135 + " -targets " + targetPlatformIdentifiers; //$NON-NLS-1$ |
|
136 } |
|
137 else if( toolchainNameStr.compareToIgnoreCase( "GCC" ) == 0 ){ //$NON-NLS-1$ |
|
138 |
|
139 // An example GCC command line |
|
140 // appdep GCC -tools %GCC_TOOLS% -cache %CACHE_DIR% -release %SDK_ROOT% |
|
141 // -targets THUMB %OPT% %COMMAND% %COMPONENT% |
|
142 |
|
143 parameters = "-tools " + "\"" + settings.getGccToolsDir() + "\"" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
|
144 + " -cache " + "\"" + settings.getCacheBaseDirForCurrentlyUsedSdk() + "\"" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
|
145 + " -release " + "\"" + settings.getSdkRootDir() + "\"" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
|
146 + " -targets " + targetPlatformIdentifiers; //$NON-NLS-1$ |
|
147 } |
|
148 else{ |
|
149 // This is an internal error if we ever get into here |
|
150 throw new InvalidCmdLineToolSettingException( |
|
151 Messages.getString("AppDepCoreFacade.UnexpectedException_In_prepareParameters_Method") //$NON-NLS-1$ |
|
152 + ". " //$NON-NLS-1$ |
|
153 + Messages.getString("AppDepCoreFacade.Toolchain_Str") //$NON-NLS-1$ |
|
154 + "'" //$NON-NLS-1$ |
|
155 + toolchainNameStr |
|
156 + "' " //$NON-NLS-1$ |
|
157 + Messages.getString("AppDepCoreFacade.Is_Not_Supported_Msg_End") //$NON-NLS-1$ |
|
158 + "!" ); //$NON-NLS-1$ |
|
159 } |
|
160 |
|
161 if(settings.getBuildType() instanceof BuildTypeDebug){ |
|
162 parameters += " --useudeb "; //$NON-NLS-1$ |
|
163 } |
|
164 |
|
165 if(checkFromCacheGenerOpts && cacheGenerOptionsAreSet()){ |
|
166 if(cacheGenerOpts.getUsedLibraryType() == CacheGenerationOptions.USE_LIB_FILES |
|
167 && |
|
168 // This option is unnecessary for GCC toolchain |
|
169 ! toolchainNameStr.equalsIgnoreCase(AppDepSettings.STR_GCC)){ |
|
170 parameters += " --uselibs "; //$NON-NLS-1$ |
|
171 } |
|
172 } |
|
173 |
|
174 return parameters; |
|
175 } |
|
176 |
|
177 /** |
|
178 * Guard for accessing cache generation options. |
|
179 * @return <code>true</code> if options can be accessed safely, otherwise <code>false</code>. |
|
180 */ |
|
181 private boolean cacheGenerOptionsAreSet() { |
|
182 return (settings.getCacheGenerOptions() != null); |
|
183 } |
|
184 |
|
185 public void generateCache(Job jobContext) throws InvalidCmdLineToolSettingException{ |
|
186 |
|
187 // Enabling the check from cache generation options |
|
188 checkFromCacheGenerOpts = true; |
|
189 |
|
190 ICustomLineReader stdErrReader = null; |
|
191 |
|
192 ITargetPlatform[] toStripTargetList = settings.getCurrentlyUsedTargetPlatforms(); |
|
193 // Stripping away SIS target |
|
194 ArrayList<ITargetPlatform> strippedTargetList = new ArrayList<ITargetPlatform>(); |
|
195 for (int i = 0; i < toStripTargetList.length; i++) { |
|
196 ITargetPlatform platform = toStripTargetList[i]; |
|
197 if(! platform.getId().equalsIgnoreCase(AppDepSettings.TARGET_TYPE_ID_SIS)){ |
|
198 checkCacheDirectoryExistenceAndCreateIfNeeded(platform.getId()); |
|
199 strippedTargetList.add(platform); |
|
200 } |
|
201 } |
|
202 |
|
203 currentlySelectedTargets = strippedTargetList.toArray(new TargetPlatform[0]); |
|
204 |
|
205 // Setting up fields that are used to build the command |
|
206 options = "--refresh"; // Forcing cache refres //$NON-NLS-1$ |
|
207 |
|
208 stdErrReader = new CacheCreationProgressLineReader(); |
|
209 if(settings.isInSISFileAnalysisMode()){ |
|
210 String sisOptions = getSISGenerationOptions(); |
|
211 commands = sisOptions; |
|
212 }else{ |
|
213 commands = ""; // No command is needed, generating only cache //$NON-NLS-1$ |
|
214 } |
|
215 |
|
216 executeCommand(null, stdErrReader, jobContext); |
|
217 |
|
218 // Disabling the check from cache generation options |
|
219 checkFromCacheGenerOpts = false; |
|
220 } |
|
221 |
|
222 /** |
|
223 * Get -sisfiles "<files user has been selected>" -options for SIS cache generation. |
|
224 * @return -sisfiles "<files user has been selected>". User selected files are semi |
|
225 * comma separated. |
|
226 */ |
|
227 private String getSISGenerationOptions(){ |
|
228 |
|
229 String[] sisFiles = settings.getSISFilesForAnalysis(); |
|
230 |
|
231 StringBuffer sisCommand = new StringBuffer(); |
|
232 sisCommand.append("-sisfiles \""); //$NON-NLS-1$ |
|
233 |
|
234 for (int i = 0; i < sisFiles.length; i++) { |
|
235 sisCommand.append(sisFiles[i]); |
|
236 if(i != sisFiles.length -1){ |
|
237 sisCommand.append(";"); //$NON-NLS-1$ |
|
238 } |
|
239 } |
|
240 |
|
241 sisCommand.append("\""); //$NON-NLS-1$ |
|
242 |
|
243 return sisCommand.toString(); |
|
244 } |
|
245 |
|
246 public void getComponentsThatUsesComponent(String componentName, |
|
247 ArrayList<String> resultLinesArrayList, |
|
248 Job jobContext) throws InvalidCmdLineToolSettingException{ |
|
249 |
|
250 ICustomLineReader stdOutReader = null; |
|
251 |
|
252 currentlySelectedTargets = settings.getCurrentlyUsedTargetPlatforms(); |
|
253 |
|
254 options = ""; // No special options are needed //$NON-NLS-1$ |
|
255 stdOutReader = new LinesToStringArrayListCustomLineReader(resultLinesArrayList); |
|
256 commands = "-dependson " + componentName; //$NON-NLS-1$ |
|
257 |
|
258 executeCommand(stdOutReader, null, jobContext); |
|
259 } |
|
260 |
|
261 public void getComponentsThatUsesFunction(String componentName, |
|
262 String functionOrdinal, |
|
263 ArrayList<String> resultLinesArrayList, |
|
264 Job jobContext) throws InvalidCmdLineToolSettingException{ |
|
265 |
|
266 ICustomLineReader stdOutReader = null; |
|
267 |
|
268 currentlySelectedTargets = settings.getCurrentlyUsedTargetPlatforms(); |
|
269 |
|
270 options = ""; // No special options are needed //$NON-NLS-1$ |
|
271 stdOutReader = new LinesToStringArrayListCustomLineReader(resultLinesArrayList); |
|
272 commands = "-usesfunction " + componentName + "@" + functionOrdinal; //$NON-NLS-1$ //$NON-NLS-2$ |
|
273 |
|
274 executeCommand(stdOutReader, null, jobContext); |
|
275 } |
|
276 |
|
277 |
|
278 /** |
|
279 * Check the existence of cache directory, and creates |
|
280 * a new directory (whole path) if needed. |
|
281 * @param targetPlatformId Target plaform to check cache existence from. |
|
282 */ |
|
283 private void checkCacheDirectoryExistenceAndCreateIfNeeded(String targetPlatformId) { |
|
284 String cacheDirCreateFailedMsg = Messages.getString("AppDepCoreFacade.Cache_Dir_Create_Failed_Msg"); //$NON-NLS-1$ |
|
285 File cacheDir = new File(settings.getCacheDirForTarget(targetPlatformId)); |
|
286 if(cacheDir.exists()&& cacheDir.isFile()){ |
|
287 // If there already exists a file with same name => deleting it |
|
288 deleteFile(cacheDir, false); |
|
289 } |
|
290 |
|
291 if(!cacheDir.exists()){ |
|
292 // If cache directory does not exist, creating it |
|
293 if(!cacheDir.mkdirs()){ |
|
294 AppDepConsole.getInstance().println(cacheDirCreateFailedMsg, IConsolePrintUtility.MSG_ERROR); |
|
295 throw new RuntimeException(cacheDirCreateFailedMsg); |
|
296 } |
|
297 } |
|
298 } |
|
299 |
|
300 /** |
|
301 * Deletes the file given as argument. |
|
302 * @param fileToBeDeleted File to be deleted. |
|
303 * @param ignoreDeleteFailure If this is set to <code>false</code> an exception is raised |
|
304 * when delete attempt has failed, if set to <code>true</code> raises and exception if |
|
305 * delete has failed. |
|
306 */ |
|
307 private void deleteFile(File fileToBeDeleted, boolean ignoreDeleteFailure) { |
|
308 if(!fileToBeDeleted.delete()){ |
|
309 if(!ignoreDeleteFailure){ |
|
310 String fileDeleteFailedMsg = Messages.getString("AppDepCoreFacade.File_Delete_Failed_Msg") + ": " + fileToBeDeleted.getAbsolutePath(); //$NON-NLS-1$ //$NON-NLS-2$ |
|
311 AppDepConsole.getInstance().println(fileDeleteFailedMsg, IConsolePrintUtility.MSG_ERROR); |
|
312 throw new RuntimeException(fileDeleteFailedMsg); |
|
313 } |
|
314 } |
|
315 } |
|
316 |
|
317 private String[] buildCommandLine() throws InvalidCmdLineToolSettingException{ |
|
318 |
|
319 Vector<String> cmdLineVector = new Vector<String>(); |
|
320 |
|
321 try { |
|
322 // Executable |
|
323 cmdLineVector.add(settings.getAppDepProgramPathName()); |
|
324 // Toolchain |
|
325 if(checkFromCacheGenerOpts && cacheGenerOptionsAreSet()){ |
|
326 CacheGenerationOptions opt = settings.getCacheGenerOptions(); |
|
327 IToolchain toolchain = opt.getUsedToolchain(); |
|
328 cmdLineVector.add(toolchain.getToolchainName()); |
|
329 } |
|
330 else{ |
|
331 //Using current settings |
|
332 cmdLineVector.add(settings.getCurrentlyUsedToolChain().getToolchainName()); |
|
333 } |
|
334 // Parameters |
|
335 String targetPlatformIds = currentlySelectedTargets[0].getId(); |
|
336 // Combining targets ids with separateor character TARGET_SEPARATOR |
|
337 for (int i = 1; i < currentlySelectedTargets.length; i++) { |
|
338 targetPlatformIds = targetPlatformIds |
|
339 + TARGET_SEPARATOR |
|
340 + currentlySelectedTargets[i].getId(); |
|
341 } |
|
342 cmdLineVector.add(prepareParameters(targetPlatformIds)); |
|
343 |
|
344 // Options |
|
345 cmdLineVector.add(options); |
|
346 // Commands |
|
347 cmdLineVector.add(commands); |
|
348 } catch (Exception e) { |
|
349 e.printStackTrace(); |
|
350 } |
|
351 |
|
352 return cmdLineVector.toArray(new String[0]); |
|
353 } |
|
354 |
|
355 /** |
|
356 * Builds the command line and runs the given command. |
|
357 * The current version support only one command to be executed |
|
358 * at a time. Therefore we are using flag that prevents |
|
359 * the execution of two commands at the same time. |
|
360 * @param cmdLineArray Command line in an array form. |
|
361 * @param stdOutReader Reference to custom stdout reader, or null if the usage |
|
362 * of the default reader is what is wanted. |
|
363 * @param stdErrReader Reference to custom stderr reader, or null if the usage |
|
364 * of the default reader is what is wanted. |
|
365 * @throws InvalidCmdLineToolSettingException |
|
366 */ |
|
367 private void executeCommand(ICustomLineReader stdOutReader, |
|
368 ICustomLineReader stdErrReader) throws InvalidCmdLineToolSettingException{ |
|
369 String[] cmdLineArr = buildCommandLine(); |
|
370 |
|
371 //If we are in SIS Analysis mode, an empty symbolics cache file must be generated |
|
372 if(settings.isInSISFileAnalysisMode()){ |
|
373 try { |
|
374 generateEmptyCacheSymbolFile(); |
|
375 } catch (Exception e) { |
|
376 //If an error occurs throwing runtime message and cache generation will not be started |
|
377 e.printStackTrace(); |
|
378 AppDepConsole.getInstance().println(Messages.getString("AppDepCoreFacade.EmptySymbolCahceFileCreation_ErrMsg") //$NON-NLS-1$ |
|
379 +e.getMessage(), AppDepConsole.MSG_ERROR); |
|
380 throw new RuntimeException(e.getMessage()); |
|
381 } |
|
382 } |
|
383 |
|
384 cmdLineExecutor.runCommand(cmdLineArr, stdOutReader, stdErrReader, currentJobContext); |
|
385 |
|
386 } |
|
387 |
|
388 /** |
|
389 * Create an empty code>appdep-cache_symbol_tables.txt</code> -file |
|
390 * because <code>appdep.exe</code> in SIS mode does not create one |
|
391 * and other cache handling logic requires one. |
|
392 * |
|
393 * @throws IOException if on error occurs |
|
394 */ |
|
395 private void generateEmptyCacheSymbolFile() throws Exception { |
|
396 String filePath = settings.getCacheBaseDirForCurrentlyUsedSdk() + |
|
397 File.separatorChar + SIS_PATH + |
|
398 File.separatorChar + ProductInfoRegistry.getCacheSymbolsFileName(); |
|
399 |
|
400 DbgUtility.println(DbgUtility.PRIORITY_OPERATION,"Generating empty symbol cache file to: " +filePath);//$NON-NLS-1$ |
|
401 |
|
402 StringBuffer b = new StringBuffer(); |
|
403 b.append(ProductInfoRegistry.getCacheSymbolTablesFileContentPrefix()); |
|
404 b.append(" ");//$NON-NLS-1$ |
|
405 b.append(ProductInfoRegistry.getSupportedCacheFileVersionInfoString()); |
|
406 b.append("\n");//$NON-NLS-1$ |
|
407 b.append(CacheDataConstants.CACHE_FILE_END_MARK); |
|
408 |
|
409 FileUtils.writeToFile(filePath, b.toString()); |
|
410 } |
|
411 |
|
412 /** |
|
413 * Wrapper to to the referenced executeComman. Just stores |
|
414 * job context that enables to add created worker thread |
|
415 * to the job context. |
|
416 * @param cmdLineArray Command line in an array form. |
|
417 * @param stdOutReader Reference to custom stdout reader, or null if the usage |
|
418 * of the default reader is what is wanted. |
|
419 * @param stdErrReader Reference to custom stderr reader, or null if the usage |
|
420 * of the default reader is what is wanted. |
|
421 * @param jobContext Job object under which the command will be executed. |
|
422 * @throws InvalidCmdLineToolSettingException |
|
423 */ |
|
424 private void executeCommand(ICustomLineReader stdOutReader, |
|
425 ICustomLineReader stdErrReader, |
|
426 Job jobContext) throws InvalidCmdLineToolSettingException{ |
|
427 currentJobContext = jobContext; |
|
428 executeCommand(stdOutReader, |
|
429 stdErrReader); |
|
430 } |
|
431 |
|
432 |
|
433 /** |
|
434 * Just delegating the call further to the real observer. |
|
435 * @see com.nokia.s60tools.util.cmdline.ICmdLineCommandExecutorObserver#progress(int) |
|
436 */ |
|
437 public void progress(int percentage) { |
|
438 observer.progress(percentage); |
|
439 } |
|
440 |
|
441 /** |
|
442 * Setting down execution flag and delegating |
|
443 * the call further to the real observer. |
|
444 * @see com.nokia.s60tools.util.cmdline.ICmdLineCommandExecutorObserver#completed(int) |
|
445 */ |
|
446 public void interrupted(String reasonMsg) { |
|
447 observer.interrupted(reasonMsg); |
|
448 } |
|
449 |
|
450 /** |
|
451 * Just delegating the call further to the real observer. |
|
452 * @see com.nokia.s60tools.util.cmdline.ICmdLineCommandExecutorObserver#progress(int) |
|
453 */ |
|
454 public void processCreated(Process proc) { |
|
455 observer.processCreated(proc); |
|
456 } |
|
457 |
|
458 /** |
|
459 * Setting down execution flag and delegating |
|
460 * the call further to the real observer. |
|
461 * @see com.nokia.s60tools.util.cmdline.ICmdLineCommandExecutorObserver#completed(int) |
|
462 */ |
|
463 public void completed(int exitValue) { |
|
464 observer.completed(exitValue); |
|
465 } |
|
466 |
|
467 } |