--- 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;
- }
-
-}