diff -r b685c59de105 -r fe49e33862e2 themeinstaller/source/src/com/nokia/tools/themeinstaller/installationmanager/ManifestFactory.java --- a/themeinstaller/source/src/com/nokia/tools/themeinstaller/installationmanager/ManifestFactory.java Thu Aug 19 09:43:47 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,593 +0,0 @@ -/* - * Copyright (c) 2007 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: Uses XML parser to read the manifest and created objects that - * represent the manifest. - * - */ - -package com.nokia.tools.themeinstaller.installationmanager; - -import java.io.File; -import java.io.IOException; -import java.util.Enumeration; -import java.util.Vector; - -import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.nokia.tools.themeinstaller.localisation.DTDReader; -import com.nokia.tools.themeinstaller.localisation.Localisation; -import com.nokia.tools.themeinstaller.localisation.LocalisationStore; -import com.nokia.tools.themeinstaller.odtconverter.ConverterProperties; -import com.nokia.tools.themeinstaller.odtconverter.IParseOperationListener; -import com.nokia.tools.themeinstaller.odtconverter.MimeTypeResolver; -import com.nokia.tools.themeinstaller.odtconverter.ThemeStatusResolver; -import com.nokia.tools.themeinstaller.xmlparser.XMLParser; - -/** - * Uses XML parser to read the manifest and created objects that represent the - * manifest. - */ -public class ManifestFactory implements IParseOperationListener { - - // CONSTANTS - // Manifest root node names - private static final String MULTI_THEME = "datfiles"; - - // Manifest element names - private static final String APP_UID_ELEMENT = "AppUid"; - private static final String PROVIDER_UID_ELEMENT = "Provideruid"; - private static final String THEME_UID_ELEMENT = "ThemeUid"; - private static final String THEME_STATUS_ELEMENT = "ThemeStatus"; - private static final String THEME_FULL_NAME_ELEMENT = "ThemeFullName"; - private static final String THEME_SHORT_NAME_ELEMENT = "ThemeShortName"; - private static final String THEME_VERSION_ELEMENT = "ThemeVersion"; - private static final String FILE_XML_ELEMENT = "FileXML"; - private static final String FILE_CSS_ELEMENT = "FileCSS"; - private static final String FILE_DTD_ELEMENT = "FileDTD"; - private static final String FILE_DAT_ELEMENT = "FileDAT"; - private static final String FILE_RESOURCE_ELEMENT = "FileResource"; - private static final String CACHE_VALUE_MEMORY = "CacheMemory"; - private static final String LOCKING_ELEMENT = "Locking"; - private static final String LOCKED_VALUE = "Locked"; - private static final String CACHE_TYPE_ELEMENT = "CacheType"; - private static final String CACHE_VALUE_NONE = "CacheNone"; - private static final String CACHE_VALUE_FILE = "CacheFile"; - - // Language element names - private static final String LANGUAGE_SPECIFIC_ELEMENT = "LanguageSpecific"; - private static final int LANGUAGE_INDEPENDENT = 0; - private static final int LANG_NOT_SET = -1; - - // Integer conversion radix - private static final int RADIX = 16; - - // Screen size - private static final int SCREEN_SIZE_X = 0; - private static final int SCREEN_SIZE_Y = 0; - - // Resource file cache type - public static int CACHE_TYPE_CACHE_NONE = 0; - public static int CACHE_TYPE_CACHE_FILE = 1; - public static int CACHE_TYPE_CACHE_MEMORY = 2; - - // Locking policy flag-definition from native, bit-masked. - public static final int E_XN_UNLOCKED = 0x0000; // 0b0000000000000000, - public static final int E_XN_LOCKED = 0x0001; // 0b0000000000000001, - - public static final String CURRENT_DIR = "."; - - // Property keys - private static final String THEME_PROVIDER_KEY = "theme_provider_name"; - private static final String NAME_SPACE_KEY = "theme_name_space"; - - // Lock for monitoring parse operation completions - private Lock iLock; - - // Mime type resolver - private MimeTypeResolver iMimeTypeResolver; - - // Converter properties - private ConverterProperties iProperties; - - // Localisation settings - private File iLocSettings; - - /** - * Constructor. - * - * @param aLocSettings - * Localisation settings - * @throws IOException - * if converter properties can not be read - */ - public ManifestFactory(File aLocSettings) throws IOException { - iLock = new Lock(); - iMimeTypeResolver = new MimeTypeResolver(); - iProperties = ConverterProperties.getInstance(); - iLocSettings = aLocSettings; - } - - /** - * Parse a manifest and create the manifest object. - * - * @param aFile - * Manifest file - * @return Manifest instance - * @throws IOException - * if the manifest can not be read - */ - public IThemeManifest createManifest(File aFile) throws IOException { - // Read the manifest to the DOM document - Document document = readManifest(aFile); - IThemeManifest manifest = new ThemeManifest(); - - // Set data directory that contains the data files of the theme - if (aFile.getParent() == null) { - manifest.setDataDir(CURRENT_DIR + File.separatorChar); - } else { - manifest.setDataDir(aFile.getParent() + File.separatorChar); - } - - // Parse manifest contents - String rootNodeName = document.getFirstChild().getNodeName(); - if (rootNodeName == MULTI_THEME) { - // Multi theme manifest - parseMultiThemeManifest(document, manifest); - } else { - // Single theme manifest - parseManifest(document, manifest); - parseLanguageSpecificData(document, manifest); - parseResources(document, manifest, LANGUAGE_INDEPENDENT); - } - - return manifest; - } - - /* - * (non-Javadoc) - * - * @seecom.nokia.tools.themeinstaller.odtconverter.IParseOperationListener# - * parseOperationCompleted(int, java.lang.String) - */ - public void parseOperationCompleted(int aErr, String aReason) { - iLock.unLock(); - if (aErr != 0) { - throw new IllegalArgumentException( - "Theme manifest parsing failed: " + aErr + ", " + aReason); - } - } - - /** - * Parse the manifest file. - * - * @param aManifest - * Manifest file - * @return DOM Document of the manifest - */ - private Document readManifest(File aManifest) { - // Parse the manifest - XMLParser parser = new XMLParser(aManifest.getPath()); - parser.addListener(this); - - try { - parser.parse(); - } catch (Exception e) { - throw new IllegalArgumentException( - "Theme manifest parsing failed: " + e.getMessage()); - } - - // Wait for the operation completion - iLock.lock(); - - // Return the document that was formed - return parser.getDOMDocument(); - } - - /** - * Parses a multi theme manifest from DOM to the manifest instance. - * - * @param aDocument - * DOM Document containing the manifest data (source) - * @param aManifest - * Theme manifest (destination) - */ - private void parseMultiThemeManifest(Document aDocument, - IThemeManifest aManifest) { - // Add DAT file names - NodeList nodes = aDocument.getElementsByTagName(FILE_DAT_ELEMENT); - Node node = null; - for (int i = 0; i < nodes.getLength(); i++) { - node = nodes.item(i); - aManifest.addManifestFile(aManifest.getDataDir() - + node.getTextContent()); - } - } - - /** - * Parses a manifest from DOM to the manifest instance. - * - * @param aDocument - * DOM Document containing the manifest data (source) - * @param aManifest - * Theme manifest (destination) - */ - private void parseManifest(Document aDocument, IThemeManifest aManifest) { - // Set application uid - NodeList nodes = aDocument.getElementsByTagName(APP_UID_ELEMENT); - Node node = checkOneNode(nodes, APP_UID_ELEMENT); - if (node != null) - aManifest.setApplicationUid(Long.valueOf(node.getTextContent(), - RADIX)); - - // Set provider uid - nodes = aDocument.getElementsByTagName(PROVIDER_UID_ELEMENT); - node = checkOneNode(nodes, PROVIDER_UID_ELEMENT); - if (node != null) - aManifest - .setProviderUid(Long.valueOf(node.getTextContent(), RADIX)); - - // Set theme uid - nodes = aDocument.getElementsByTagName(THEME_UID_ELEMENT); - node = checkOneNode(nodes, THEME_UID_ELEMENT); - if (node != null) - aManifest.setThemeUid(Long.valueOf(node.getTextContent(), RADIX)); - - // Set name space - aManifest.setNameSpace(iProperties.getProperty(NAME_SPACE_KEY)); - - // Set theme provider name - aManifest.setProviderName(iProperties.getProperty(THEME_PROVIDER_KEY)); - - // Set default theme full name before localization - nodes = aDocument.getElementsByTagName(THEME_FULL_NAME_ELEMENT); - if (nodes.getLength() > 0) { - // Get first theme name that is found (for a default name). - // The used name is specified in the language specific data. - aManifest.setThemeFullName(nodes.item(0).getTextContent()); - } - // else - // { - // throw new IllegalArgumentException( - // "Syntax error in manifest file: theme full name not found" ); - // } - - // Set theme short name - nodes = aDocument.getElementsByTagName(THEME_SHORT_NAME_ELEMENT); - node = checkOneNode(nodes, THEME_SHORT_NAME_ELEMENT); - if (node != null) - aManifest.setThemeShortName(node.getTextContent()); - - // Set theme version - nodes = aDocument.getElementsByTagName(THEME_VERSION_ELEMENT); - node = checkOneNode(nodes, THEME_VERSION_ELEMENT); - if (node != null) - aManifest.setThemeVersion(node.getTextContent()); - - // Screen size, not used in Xuikon at the moment - aManifest.setScreenSizeX(new Integer(SCREEN_SIZE_X)); - aManifest.setScreenSizeY(new Integer(SCREEN_SIZE_Y)); - - // Resolve theme status - nodes = aDocument.getElementsByTagName(THEME_STATUS_ELEMENT); - int flags = ThemeStatusResolver.E_XN_THEME_STATUS_NONE; - for (int i = 0; i < nodes.getLength(); i++) { - node = nodes.item(i); - flags |= ThemeStatusResolver.getValue(node.getTextContent()) - .intValue(); - if (node.getTextContent().equals( - ThemeStatusResolver.THEME_STATUS_LICENCEE_RESTORABLE)) { - // This theme is restored when licensee default theme is - // restored. - // When using this flag, the ThemeStatusLicenceeDefault-flag - // must be activated. - flags |= ThemeStatusResolver.E_XN_THEME_STATUS_LICENCEE_DEFAULT; - } - } - aManifest.setThemeStatus(new Integer(flags)); - - // Set XML file name - NodeList files = aDocument.getElementsByTagName(FILE_XML_ELEMENT); - node = checkOneNode(files, FILE_XML_ELEMENT); - if (node != null) - aManifest.setXMLFile(node.getTextContent()); - - // Set CSS file name - files = aDocument.getElementsByTagName(FILE_CSS_ELEMENT); - node = checkMaxOneLanguageIndependentNode(files); - if (node != null) { - aManifest.setCSSFile(node.getTextContent()); - } - - // Set DTD file name - files = aDocument.getElementsByTagName(FILE_DTD_ELEMENT); - node = checkMaxOneLanguageIndependentNode(files); - if (node != null) { - aManifest.setDTDFile(node.getTextContent()); - } - } - - /** - * Parses language specific data in the manifest. - * - * @param aDocument - * DOM Document containing the manifest data (source) - * @param aManifest - * Theme manifest (destination) - * @throws IOException - * if the manifest can not be parsed - */ - private void parseLanguageSpecificData(Document aDocument, - IThemeManifest aManifest) throws IOException { - // Get languages - NodeList languages = aDocument - .getElementsByTagName(LANGUAGE_SPECIFIC_ELEMENT); - - Node langSpecificNode = null; - NamedNodeMap langAttr = null; - NodeList langSpecificChildren = null; - Node langSpecificChild = null; - - NodeList resources = aDocument - .getElementsByTagName(FILE_RESOURCE_ELEMENT); - Vector langResources = null; - - // Process all languages - for (int i = 0; i < languages.getLength(); i++) { - // Language specific data - int langId = LANG_NOT_SET; - String extDtd = null; - String extCss = null; - String themeFullName = null; - - // Take a LanguageSpecific node - langSpecificNode = languages.item(i); - - // There should be only one language for each LanguageSpecific node - langAttr = langSpecificNode.getAttributes(); - if (langAttr.getLength() == 1) { - String langStr = langAttr.item(0).getNodeValue(); - langId = Integer.valueOf(langStr).intValue(); - } - - langSpecificChildren = langSpecificNode.getChildNodes(); - - // Read language specific elements - String nodeName = null; - - for (int j = 0; j < langSpecificChildren.getLength(); j++) { - langSpecificChild = langSpecificChildren.item(j); - nodeName = langSpecificChild.getNodeName(); - - // Language specific DTD file name - if (FILE_DTD_ELEMENT.equals(nodeName)) { - extDtd = langSpecificChild.getTextContent(); - } - // Language specific CSS - else if (FILE_CSS_ELEMENT.equals(nodeName)) { - extCss = langSpecificChild.getTextContent(); - } - // Localized theme full name - else if (THEME_FULL_NAME_ELEMENT.equals(nodeName)) { - themeFullName = langSpecificChild.getTextContent(); - } - } - - // Parse language specific resources - langResources = parseResources(aManifest, resources, langId); - - // Verify that mandatory fields language id and DTD file were set - if (langId == LANG_NOT_SET || extDtd == null) { - throw new IllegalArgumentException( - "Syntax error in language specifications of the manifest"); - } - - // Find the DTD file for reading the localised theme full name - File dtd = null; - if (iLocSettings != null) { - // Use enhanced localisation: Find the DTD file - LocalisationStore ls = LocalisationStore - .getInstance(iLocSettings); - Localisation l = ls.getLocalisation(aManifest - .getApplicationUid().longValue(), aManifest - .getProviderUid().longValue(), aManifest.getThemeUid() - .longValue()); - dtd = l.findDTD(extDtd); - } else { - dtd = new File(aManifest.getDataDir() + extDtd); - } - - // Resolve localised theme full name, if specified - themeFullName = DTDReader.readEntity(dtd, themeFullName); - - // Create new language specific data and add it to the languages - // list - LanguageSpecificData language = new LanguageSpecificData( - new Integer(langId), extDtd, extCss, themeFullName, - langResources); - aManifest.addLanguage(language); - } - - // Unlocalized variant (causes the .o0000 file to be generated) - LanguageSpecificData language = new LanguageSpecificData(new Integer( - LANGUAGE_INDEPENDENT), null, null, null, null); - aManifest.addLanguage(language); - } - - /** - * Parses resource data in the manifest. - * - * @param aDocument - * DOM Document containing the manifest data (source) - * @param aManifest - * Theme manifest (destination) - * @param aLanguageId - * Id of the language of which resources will be parsed. On 0, - * only language independent resources are parsed. - */ - private void parseResources(Document aDocument, IThemeManifest aManifest, - int aLanguageId) { - // Do the parsing operation - NodeList resourceList = aDocument - .getElementsByTagName(FILE_RESOURCE_ELEMENT); - Vector resources = parseResources(aManifest, resourceList, aLanguageId); - - // Add resources to the manifest - Enumeration e = resources.elements(); - while (e.hasMoreElements()) { - aManifest.addResource((ThemeResource) e.nextElement()); - } - } - - /** - * Parses resource files defined in the manifest. Resources must be parsed - * after the rest of the manifest is parsed. Theme status is used here for - * determining locking policies. - * - * @param aManifest - * Theme manifest - * @param aNodeList - * Node list to parse - * @param aLanguageId - * Id of the language of which resources will be parsed. On 0, - * only language independent resources are parsed. - */ - private Vector parseResources(IThemeManifest aManifest, NodeList aNodeList, - int aLanguageId) { - Vector result = new Vector(); - Node node = null; - - // Browse through all resources in the list - int count = aNodeList.getLength(); - for (int i = 0; i < count; i++) { - node = aNodeList.item(i); - String filename = node.getTextContent(); - NamedNodeMap attributes = node.getAttributes(); - - int cacheType = CACHE_TYPE_CACHE_NONE; - int lockingPolicy = E_XN_UNLOCKED; - - // Set cache type - Node cacheTypeNode = attributes.getNamedItem(CACHE_TYPE_ELEMENT); - if ((cacheTypeNode == null) - || cacheTypeNode.getTextContent().equals(CACHE_VALUE_NONE)) { - cacheType = CACHE_TYPE_CACHE_NONE; - } else if (cacheTypeNode.getTextContent().equals(CACHE_VALUE_FILE)) { - cacheType = CACHE_TYPE_CACHE_FILE; - } else if (cacheTypeNode.getTextContent() - .equals(CACHE_VALUE_MEMORY)) { - cacheType = CACHE_TYPE_CACHE_MEMORY; - } else { - throw new IllegalArgumentException( - "Syntax error in the manifest, can not resolve resource cache type"); - } - - // Set locking policy - Node locking = attributes.getNamedItem(LOCKING_ELEMENT); - if (locking != null - && locking.getTextContent().equals(LOCKED_VALUE)) { - lockingPolicy = E_XN_LOCKED; - } - - // If EXnThemeStatusLicenceeDefault flag is set, locking policy is - // E_XN_LOCKED - if ((aManifest.getThemeStatus().intValue() & ThemeStatusResolver.E_XN_THEME_STATUS_LICENCEE_DEFAULT) != 0) { - lockingPolicy = E_XN_LOCKED; - } - - // Resolve mime type - String mime = iMimeTypeResolver.getMimeType(filename); - - // Resolve resource type - int resourceType = iMimeTypeResolver.getResourceType(filename); - - // Verify language id - Node parent = node.getParentNode(); - NamedNodeMap attr = parent.getAttributes(); - - // Language specific resources - if (attr.getLength() == 1 - && aLanguageId == Integer.valueOf( - attr.item(0).getNodeValue()).intValue()) { - ThemeResource resource = new ThemeResource(filename, cacheType, - lockingPolicy, aManifest.getNameSpace(), resourceType, - mime); - result.add(resource); - } - // Language independent resources - else if (aLanguageId == LANGUAGE_INDEPENDENT - && !LANGUAGE_SPECIFIC_ELEMENT.equals(parent.getNodeName())) { - ThemeResource resource = new ThemeResource(filename, cacheType, - lockingPolicy, aManifest.getNameSpace(), resourceType, - mime); - result.add(resource); - } - } - - return result; - } - - /** - * Checks that there exists just one node in the list - * - * @param aNodeList - * Node list to be checked - * @return Only one existing node - * @throws IllegalArgumentException - * If there is more or less than one node in list - */ - private Node checkOneNode(NodeList aNodeList, String tagName) { - - if (aNodeList.getLength() > 1) { - throw new IllegalArgumentException( - "Syntax error in manifest file, more child nodes than expected"); - } - return aNodeList.item(0); - } - - /** - * Checks that there exists max one node in the list and it is language - * independent. - * - * @param aNodeList - * Node list to be checked - * @return The existing language independent node or null - * @throws IllegalArgumentException - * If there is more or less than one node in list - */ - private Node checkMaxOneLanguageIndependentNode(NodeList aNodeList) { - Node result = null; - int count = 0; - for (int i = 0; i < aNodeList.getLength(); i++) { - // Verify language in-dependency - Node node = aNodeList.item(i); - Node parent = node.getParentNode(); - if (!LANGUAGE_SPECIFIC_ELEMENT.equals(parent.getNodeName())) { - result = node; - count++; - } - } - - if (count > 1) { - throw new IllegalArgumentException( - "Syntax error in manifest file, more language " - + "independent child nodes than expected"); - } - - return result; - } - -}