diff -r 000000000000 -r 522a326673b6 sysmodelmgr/com.symbian.smt.gui/src/com/symbian/smt/gui/builder/SMTCommand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sysmodelmgr/com.symbian.smt.gui/src/com/symbian/smt/gui/builder/SMTCommand.java Thu Mar 11 19:08:43 2010 +0200 @@ -0,0 +1,465 @@ +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +package com.symbian.smt.gui.builder; + +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.BORDER_SHAPES_FILES; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.BORDER_STYLES_FILES; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.COLOURS_FILES; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.COPYRIGHT_TEXT; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.DEPENDENCIES_FILES; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.DISTRIBUTION_TEXT; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.FILTER_HAS_ITEMS; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.FIX_ITEM_SIZE; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.HIGHTLIGHT_CORE_OS; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.IGNORE_ITEMS; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.LEVELS_FILES; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.LEVEL_OF_DETAIL; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.LOCALISATION_FILES; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.MODEL_NAME; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.MODEL_VERSION; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.MODEL_VERSION_TEXT; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.OUTPUT_FILE; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.PATTERNS_FILES; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.PRINTED_DPI; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.S12_XML_FILES; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.SHAPES_FILES; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.SUPPRESS_MOUSE_OVER_EFFECT; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.SYSTEM_DEFINITION_FILES; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.SYSTEM_INFO_FILES; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.SYSTEM_NAME; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.SYSTEM_VERSION; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.TEMPDIR; +import static com.symbian.smt.gui.builder.SystemModelGeneratorEnumsForCLI.WARNING_LEVEL; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.xml.parsers.ParserConfigurationException; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ProjectScope; +import org.eclipse.core.runtime.preferences.DefaultScope; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.IScopeContext; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.swt.widgets.Display; +import org.xml.sax.SAXException; + +import com.symbian.smt.gui.Activator; +import com.symbian.smt.gui.Logger; +import com.symbian.smt.gui.PersistentDataStore; +import com.symbian.smt.gui.SystemDefinition; +import com.symbian.smt.gui.SystemDefinitionValidationException; +import com.symbian.smt.gui.SystemDefinitionValidationFatalException; +import com.symbian.smt.gui.views.ConsoleOutput; + +public class SMTCommand { + + private static String SMG_FOLDER = ""; // The location of the System Model + // Generator + private static String SMT_COMMAND = ""; // The perl script to run for the + // System Model Generator + final static String TEMP_FOLDER = ".svg_temp"; // Folder names stating with + // a . will not be displayed + // in the project navigator + private IFolder svgTempFolder; + private IProject project; + private ArrayList command = new ArrayList();; + + private PersistentDataStore defaultStore; + private PersistentDataStore instanceStore; + private PersistentDataStore projectStore; + + private Pattern ampersandPattern = Pattern.compile("&", + Pattern.CASE_INSENSITIVE); + private Pattern lessThanPattern = Pattern.compile("<", + Pattern.CASE_INSENSITIVE); + private Pattern greaterThanPattern = Pattern.compile(">", + Pattern.CASE_INSENSITIVE); + private Pattern singleQuotePattern = Pattern.compile("'", + Pattern.CASE_INSENSITIVE); + private Pattern doubleQuotePattern = Pattern.compile("\"", + Pattern.CASE_INSENSITIVE); + + public SMTCommand(IProject project) { + this.project = project; + svgTempFolder = project.getFolder(TEMP_FOLDER); + + final ResourceBundle resourceBundle = ResourceBundle.getBundle( + "location", Locale.getDefault(), this.getClass() + .getClassLoader()); + + SMG_FOLDER = resourceBundle.getString("location"); + + try { + SMT_COMMAND = new File(SMG_FOLDER + File.separator + "SysModGen.pl") + .getCanonicalPath(); + } catch (IOException e) { + Logger.log(e.getMessage(), e); + } + } + + /** + * Generates the command line string for the System Model Toolkit + * + * @return List Arguments for the CLI + */ + public List generateCommand() { + // Set up access to the persistent data stores + IScopeContext defaultScope = new DefaultScope(); + IEclipsePreferences defaultNode = defaultScope + .getNode(Activator.PLUGIN_ID); + defaultStore = new PersistentDataStore(defaultNode); + + IScopeContext instanceScope = new InstanceScope(); + IEclipsePreferences instanceNode = instanceScope + .getNode(Activator.PLUGIN_ID); + instanceStore = new PersistentDataStore(instanceNode, defaultNode); + + IScopeContext projectScope = new ProjectScope(project); + IEclipsePreferences projectNode = projectScope + .getNode(Activator.PLUGIN_ID); + projectStore = new PersistentDataStore(projectNode); + + // Required to use the SMT script + command.add("perl"); + command.add(SMT_COMMAND); + + // Add the system definition files + String[] sysDefFiles = projectStore.getSystemDefinitionFiles(); + + // The while loop below protects against concurrency conditions which + // are encountered when the sys def file is a URL resource and + // when we are creating a new project via the NewSMTProjectWizard. + while (sysDefFiles.length == 0) { + try { + Thread.sleep(10); + } catch (InterruptedException ignore) { + } + + sysDefFiles = projectStore.getSystemDefinitionFiles(); + } + + command.add(SYSTEM_DEFINITION_FILES.arg()); + + // Check that the system definition files are valid + // Only fatal errors cause the build attempt to be aborted. + // + for (String filename : sysDefFiles) { + try { + SystemDefinition.checkValidSystemDefinitionFile(filename); + } catch (SystemDefinitionValidationFatalException e1) { + writeToConsoleOutput("Error: " + filename + + " is not a valid system definition file:\n" + + e1.getMessage()); + Logger.log("Validation of system definition file ("+filename+") failed.", e1); + return null; + } catch (SystemDefinitionValidationException e1) { + Logger.log("Validation of system definition file ("+filename+") failed.", e1); + } + } + + // There may be multiple system definition files, if there are they need + // to be joined with a , + if (sysDefFiles.length == 1) { + command.add(prepareArg(sysDefFiles[0])); + } else { + StringBuilder sysDefJoined = new StringBuilder(); + + for (String file : sysDefFiles) { + sysDefJoined.append(file); + sysDefJoined.append(","); + } + + command.add(prepareArg(sysDefJoined.toString())); + } + + // Add the resources + // Default files in this context mean file the user selected + handleResource(SHAPES_FILES, projectStore.getSelectedShapesFiles()); + handleResource(LEVELS_FILES, projectStore.getSelectedLevelsFiles()); + handleResource(SYSTEM_INFO_FILES, projectStore + .getSelectedSystemInfoFiles()); + handleResource(DEPENDENCIES_FILES, projectStore + .getSelectedDependenciesFiles()); + handleResource(COLOURS_FILES, projectStore.getSelectedColoursFiles()); + handleResource(BORDER_SHAPES_FILES, projectStore + .getSelectedBorderShapesFiles()); + handleResource(PATTERNS_FILES, projectStore.getSelectedPatternsFiles()); + handleResource(LOCALISATION_FILES, projectStore + .getSelectedLocalisationFiles()); + handleResource(BORDER_STYLES_FILES, projectStore + .getSelectedBorderStylesFiles()); + handleResource(S12_XML_FILES, projectStore.getSelectedS12XmlFiles()); + + // Add the model labels + command.add(COPYRIGHT_TEXT.arg()); + command.add(prepareArg(projectStore.getCopyrightText())); + + command.add(SYSTEM_NAME.arg()); + command.add(prepareArg(projectStore.getSystemName())); + + command.add(DISTRIBUTION_TEXT.arg()); + command.add(prepareArg(projectStore.getSelectedDistributionText())); + + command.add(MODEL_NAME.arg()); + command.add(prepareArg(projectStore.getModelName())); + + command.add(MODEL_VERSION.arg()); + command.add(prepareArg(projectStore.getModelVersion())); + + command.add(MODEL_VERSION_TEXT.arg()); + command.add(prepareArg(projectStore.getSelectedModelVersionText())); + + command.add(SYSTEM_VERSION.arg()); + command.add(prepareArg(projectStore.getSystemVersion())); + + // Add the model control settings + command.add(HIGHTLIGHT_CORE_OS.arg()); + if (projectStore.getHighlightCoreOS().toString().equalsIgnoreCase( + "true")) { + command.add("on"); + } else { + command.add("false"); + } + + command.add(LEVEL_OF_DETAIL.arg()); + command.add(prepareArg(projectStore.getLevelOfDetail())); + + String dpi = projectStore.getSelectedPrintedDpi(); + + // The dpi option is to be added only if the user + // selected or typed in an option other than "" + if ((dpi != null) && (!dpi.equals(""))) { + command.add(PRINTED_DPI.arg()); + command.add(prepareArg(dpi)); + } + + if (projectStore.getSuppressMouseOverEffect()) { + command.add(SUPPRESS_MOUSE_OVER_EFFECT.arg()); + } + + // The fix item size option is to be added only if the user + // checked the corresponding check box + if (projectStore.getFixItemSize()) { + command.add(FIX_ITEM_SIZE.arg()); + command.add("fixed"); + } + + // Filter has Items + command.add(FILTER_HAS_ITEMS.arg()); + + String[] filterHasItems = projectStore.getFilterHasItems(); + + // No command line argument if there are no filter-has keywords + // If there are multiple filter has items, they need to be joined with a + // , + if (filterHasItems.length > 0) { + if (filterHasItems.length == 1) { + command.add(prepareArg(filterHasItems[0])); + } else { + StringBuilder filterItemsJoined = new StringBuilder(); + + for (String filter : filterHasItems) { + filterItemsJoined.append(filter); + filterItemsJoined.append(","); + } + + filterItemsJoined.deleteCharAt(filterItemsJoined.length() - 1); + command.add(prepareArg(filterItemsJoined.toString())); + } + } + + // Ignore Items + List ignoreItems = projectStore.getIgnoreItems(); + + StringBuilder ignoreItemsJoined = new StringBuilder(); + + for (String[] ignoreItem : ignoreItems) { + ignoreItemsJoined.append(ignoreItem[0]); + ignoreItemsJoined.append(":"); + ignoreItemsJoined.append(ignoreItem[1]); + ignoreItemsJoined.append(";"); + } + + command.add(IGNORE_ITEMS.arg()); + command.add(prepareArg(ignoreItemsJoined.toString())); + + // Set the temp folder to use + command.add(TEMPDIR.arg()); + command.add(prepareArg(svgTempFolder.getLocation().toString())); + + // Set the warning level + command.add(WARNING_LEVEL.arg()); + command.add(instanceStore.getWarningLevel()); + + // Set the output name + command.add(OUTPUT_FILE.arg()); + + File file = new File(project.getLocationURI().getPath()); + command.add(file.getAbsolutePath() + File.separator + + projectStore.getOutputFilename()); + + // Advanced Options + // They are added at the very end of the command line and only if + // defined by the user. + String[] options = projectStore.getAdvancedOptions(); + + if ((options != null) && (options.length > 0)) { + for (String option : options) { + command.addAll(prepareAdvancedOption(option.trim())); + } + } + + return command; + } + + + private List prepareAdvancedOption(String option) { + List options = new ArrayList(); + + String optionValue = null; + String argumentValue = null; + + if (option.indexOf(" ") > 0) { + optionValue = option.substring(0, option.indexOf(" ")); + argumentValue = option.substring(option.indexOf(" ")).trim(); + } else { + optionValue = option; + } + + while (optionValue.startsWith("-")) { + optionValue = optionValue.substring(1); + } + + options.add("--" + optionValue); + + if (argumentValue != null && argumentValue.length() != 0) { + options.add(argumentValue); + } + + return options; + } + + private void handleResource(SystemModelGeneratorEnumsForCLI option, + String[] selectedFiles) { + // In the cases below where we have no selected files, we need to define + // a "" string for compatibility with SMG, which does not like an empty array. + switch (option) { + case BORDER_SHAPES_FILES: + case BORDER_STYLES_FILES: + case COLOURS_FILES: + case LOCALISATION_FILES: + case PATTERNS_FILES: + case SHAPES_FILES: + case SYSTEM_INFO_FILES: + if (selectedFiles.length == 0) { + selectedFiles = new String[1]; + selectedFiles[0] = "\"\""; + } + + break; + + case LEVELS_FILES: + if (selectedFiles.length == 0) { + selectedFiles = new String[1]; + selectedFiles[0] = "\"\""; + } else { + if (selectedFiles[0].equals("Auto")) { + selectedFiles = new String[] {}; + } + } + + break; + + case DEPENDENCIES_FILES: + case S12_XML_FILES: + if (selectedFiles.length == 0) { + selectedFiles = new String[] {}; + } + + break; + + default: + throw new IllegalArgumentException("Unknown option [" + option + + "]"); + + } + + for (String file : selectedFiles) { + command.add(option.arg()); + command.add((file.equals("\"\"")) ? file : prepareArg(file)); + } + } + + private String prepareArg(String arg) { + // Escape any XML entities + arg = replace(arg, ampersandPattern.matcher(arg), "&"); + arg = replace(arg, lessThanPattern.matcher(arg), "<"); + arg = replace(arg, greaterThanPattern.matcher(arg), ">"); + arg = replace(arg, singleQuotePattern.matcher(arg), "'"); + arg = replace(arg, doubleQuotePattern.matcher(arg), """); + arg = arg.trim(); + + // Escape any unicode characters + StringBuffer result = new StringBuffer(); + + // Get chars as characters may be multibyte + for (char theChar : arg.toCharArray()) { + if ((int) theChar > 127) { + // Turn into XML unicode entity + result.append("&#x" + Integer.toHexString((int) theChar) + ";"); + } else { + // Characters < 128 should be the same in all code pages, we + // don't escape these for aesthetic reasons + result.append(theChar); + } + } + + return "\"" + result.toString() + "\""; + } + + private String replace(String arg, Matcher m, String replacement) { + m.reset(); + + StringBuffer result = new StringBuffer(); + + while (m.find()) { + m.appendReplacement(result, replacement); + } + + m.appendTail(result); + + return result.toString(); + } + + private void writeToConsoleOutput(final String string) { + // Writes a string to the console output view + + Display.getDefault().asyncExec(new Runnable() { + public void run() { + ConsoleOutput.addText(string); + } + }); + } +}