themeinstaller/source/src/com/nokia/tools/themeinstaller/installationmanager/InstallationManager.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/themeinstaller/source/src/com/nokia/tools/themeinstaller/installationmanager/InstallationManager.java Tue Feb 02 00:15:44 2010 +0200
@@ -0,0 +1,430 @@
+/*
+* 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: Starting point for theme install procedure.
+ *
+*/
+
+
+package com.nokia.tools.themeinstaller.installationmanager;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.Observable;
+import java.util.Observer;
+import java.util.Vector;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.traversal.NodeIterator;
+
+import com.nokia.tools.themeinstaller.defrep.DefinitionRepository;
+import com.nokia.tools.themeinstaller.defrep.IDefinitionRepository;
+import com.nokia.tools.themeinstaller.defrep.operations.FileOperation;
+import com.nokia.tools.themeinstaller.defrep.operations.FileOperationEvent;
+import com.nokia.tools.themeinstaller.odtconverter.ConverterProperties;
+import com.nokia.tools.themeinstaller.odtconverter.IParseOperationListener;
+import com.nokia.tools.themeinstaller.odtconverter.ODTDocument;
+import com.nokia.tools.themeinstaller.odtconverter.ODTHeader;
+import com.nokia.tools.themeinstaller.odtconverter.ODTInputStream;
+import com.sun.org.apache.xpath.internal.XPathAPI;
+
+/**
+ * Installation Manager class is the starting point for the theme installation
+ * procedure.
+ */
+public class InstallationManager implements Observer, IInstallationListener
+ {
+
+ protected static final String MANIFEST_SUFFIX = ".dat";
+
+ // Theme manifest file
+ private File iManifest;
+
+ // Destination root directory
+ private File iDestinationDir;
+
+ // Definition repository for file operations
+ private IDefinitionRepository iDefRep;
+
+ // Data directory containing the theme to install
+ private String iDataDir;
+
+ // Installation observer
+ private IInstallationListener iListener;
+
+ // Resource installer
+ private IResourceInstaller iResourceInstaller;
+
+ // Installation list of ongoing installations
+ private InstallationList iList;
+
+ // Lock for asynchronous operations.
+ private Lock iLock;
+
+ // Lock for multi theme installs
+ private Lock iMultiThemeLock;
+
+ // Localisation settings
+ private File iLocSettings;
+
+ //DTD may contain some errors such as missing semicolon. Set
+ //this to true if these are to be fixed. Currently passed via
+ //argument.
+ private static boolean fixDTD = false;
+
+ /**
+ * Default constructor
+ * @param aParams Installation parameters
+ * @param aListener Installation observer
+ * @throws IOException if Resource Installer can not be created
+ */
+ public InstallationManager( InstallationParameters aParams,
+ IInstallationListener aListener )
+ throws IOException
+ {
+ // Properties must be initialized before using them
+ ConverterProperties.initialize( aParams.getPropFile() );
+
+ iManifest = aParams.getManifest();
+ iLocSettings = aParams.getLocSettings();
+ iDestinationDir = aParams.getDestinationDir();
+ iListener = aListener;
+
+ // Create destination directory structure
+ if( !iDestinationDir.exists() )
+ {
+ iDestinationDir.mkdirs();
+ }
+
+ iDefRep = DefinitionRepository.getInstance();
+
+ if( iManifest.getParent() == null )
+ {
+ iDataDir = ManifestFactory.CURRENT_DIR + File.separatorChar;
+ }
+ else
+ {
+ iDataDir = iManifest.getParent() + File.separatorChar;
+ }
+
+ iResourceInstaller =
+ new ResourceInstaller( iDefRep, iDestinationDir, iDataDir);
+ iList = new InstallationList();
+ iLock = new Lock();
+ iMultiThemeLock = new Lock();
+ }
+
+
+ public static boolean isFixDTD() {
+ return fixDTD;
+ }
+
+
+ public static void setFixDTD(boolean fixDTD) {
+ InstallationManager.fixDTD = fixDTD;
+ }
+
+
+ /**
+ * Starts the actual installation
+ * Progress will be informed via listener
+ * @throws IOException If files cannot be found, or new files cannot be written
+ * @throws IllegalArgumentException If there exists syntax errors in manifest file
+ */
+ public void startInstallation() throws IOException
+ {
+ // Source parameter is a directory
+ if( iManifest.isDirectory() )
+ {
+ Enumeration manifests = searchManifests( iManifest ).elements();
+ if( manifests.hasMoreElements() )
+ {
+ // Install all found themes
+ installMultiTheme( manifests );
+ }
+ else
+ {
+ // No themes found
+ throw new IllegalArgumentException(
+ "Manifest files not found from: " + iManifest.getPath() );
+ }
+ }
+ // Source parameter is a file
+ else
+ {
+ // Parse the manifest
+ ManifestFactory factory = new ManifestFactory( iLocSettings );
+ IThemeManifest manifest = factory.createManifest( iManifest );
+
+ // Install sub themes of a multi theme manifest, if any
+ Enumeration manifests = manifest.getManifestFiles().elements();
+ if( manifests.hasMoreElements() )
+ {
+ installMultiTheme( manifests );
+ }
+ // Install a normal theme
+ else
+ {
+ installTheme( manifest, iLocSettings );
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
+ */
+ public void update( Observable aObservable, Object aEvent )
+ {
+ // Language install event
+ if( aObservable instanceof LanguageInstaller )
+ {
+ // Notify that the parsing operation has completed and
+ // the install of next language variant will start
+ iLock.unLock();
+
+ LanguageInstallEvent event = ( LanguageInstallEvent )aEvent;
+ ODTHeader header = event.getODTDocument().getODTHeader();
+ ProgressEvent pe = new ProgressEvent();
+ pe.setState( IInstallationListener.STATE_PARSED );
+ pe.setName( ( String )header.get( ODTHeader.ThemeShortName ) );
+ pe.setLanguage( (
+ ( Integer )header.get( ODTHeader.Language ) ).intValue() );
+ pe.setError( event.getErrorCode(), event.getReason() );
+
+ iListener.installationProgress( pe );
+ if( event.getErrorCode() ==
+ IParseOperationListener.OPERATION_SUCCESSFUL )
+ {
+ InputStream in = null;
+ try
+ {
+ // Store the ODT file
+ ODTDocument document = event.getODTDocument();
+ in = new ODTInputStream( document );
+
+// Source s = new DOMSource(document.getDOMDocument());
+//
+// Result r = new StreamResult(new File("C://output.xml"));
+//
+// Transformer t = TransformerFactory.newInstance().newTransformer();
+//
+// t.transform(s, r);
+
+ iDefRep.storeODT( iDestinationDir,
+ document.getODTHeader(),
+ in,
+ this );
+ }
+ catch ( Exception e )
+ {
+ pe.setError( IInstallationListener.ERROR, e.toString() );
+ iListener.installationCompleted( pe );
+ }
+ finally
+ {
+ if( in != null )
+ {
+ try
+ {
+ in.close();
+ }
+ catch ( IOException e )
+ {
+ // Ignore error
+ }
+ }
+ }
+ }
+ else
+ {
+ pe.setError( event.getErrorCode(), event.getReason() );
+ iListener.installationCompleted( pe );
+ }
+ }
+ // File operation event
+ else if( aObservable instanceof FileOperation )
+ {
+ FileOperationEvent event = ( FileOperationEvent )aEvent;
+ ProgressEvent pe = new ProgressEvent();
+ pe.setState( IInstallationListener.STATE_WRITED );
+ pe.setFileName( event.getFullDestPath() );
+ pe.setError( event.getErrorCode(), null );
+
+ if( event.getErrorCode() == FileOperationEvent.OPERATION_SUCCESSFUL )
+ {
+ pe.setFileName( event.getFullDestPath() );
+ iListener.installationProgress( pe );
+ }
+ else
+ {
+ pe.setError( event.getErrorCode(), null );
+ iListener.installationCompleted( pe );
+ }
+
+ iList.removeInstall( event.getDestPath() );
+ if( !iList.installsExist() )
+ {
+ pe.setError( event.getErrorCode(), null );
+ iListener.installationCompleted( pe );
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see com.nokia.tools.themeinstaller.installationmanager.IInstallationListener#installationProgress(com.nokia.tools.themeinstaller.installationmanager.ProgressEvent)
+ */
+ public void installationProgress( ProgressEvent aEvent )
+ {
+ // Pass the event
+ iListener.installationProgress( aEvent );
+ }
+
+ /* (non-Javadoc)
+ * @see com.nokia.tools.themeinstaller.installationmanager.IInstallationListener#installationCompleted(com.nokia.tools.themeinstaller.installationmanager.ProgressEvent)
+ */
+ public void installationCompleted( ProgressEvent aEvent )
+ {
+ // Pass the event and release the multi theme install lock
+ iListener.installationCompleted( aEvent );
+ iMultiThemeLock.unLock();
+ }
+
+ /**
+ * Install a normal theme
+ * @param aManifest Manifest file
+ * @throws IOException if resource files can not be installed
+ */
+ private void installTheme( IThemeManifest aManifest, File aLocSettings )
+ throws IOException
+ {
+ // Create unlocalized header for copying language independent resources
+ ODTHeader unlocalizedHeader =
+ LanguageInstaller.createHeader( aManifest, null );
+ Vector resources = aManifest.getResources();
+ Vector odtResources =
+ iResourceInstaller.installResources( resources, unlocalizedHeader );
+
+ // Get all languages
+ Enumeration languages =
+ aManifest.getLanguages().elements();
+
+ // Install each language variant
+ while( languages.hasMoreElements() )
+ {
+ LanguageSpecificData language =
+ ( LanguageSpecificData )languages.nextElement();
+ LanguageInstaller installer = new LanguageInstaller(
+ this, aManifest, language, aLocSettings, iResourceInstaller );
+
+ // Add language id to the log
+ iList.addInstall( language.getLanguageId() );
+
+ // Add language independent resources
+ installer.addResources( odtResources );
+
+ try
+ {
+ // Start the installation process
+ installer.install();
+
+ // Wait for the parsing process to complete
+ iLock.lock();
+ }
+ catch( Exception e )
+ {
+ // In error cases, cancel the installation
+ ProgressEvent pe = new ProgressEvent();
+ pe.setName( aManifest.getThemeShortName() );
+ pe.setLanguage( language.getLanguageId().intValue() );
+ pe.setError( IInstallationListener.ERROR, e.toString() );
+ iListener.installationCompleted( pe );
+ }
+ }
+ }
+
+ /**
+ * Install sub themes of a multi theme manifest.
+ * @param aManifests List of manifests
+ */
+ private void installMultiTheme( Enumeration aManifests )
+ {
+ while( aManifests.hasMoreElements() )
+ {
+ File f = ( File )aManifests.nextElement();
+ try
+ {
+ // Create installation parameters for the new
+ // Installation Manager instance
+ InstallationParameters params = new InstallationParameters(
+ f, iDestinationDir );
+ params.setLocSettings( iLocSettings );
+
+ // Create a new installation manager
+ InstallationManager i = new InstallationManager( params, this );
+ i.startInstallation();
+
+ // Install only a theme at a time
+ iMultiThemeLock.lock();
+ }
+ catch ( Exception e )
+ {
+ // In error cases, cancel the installation
+ ProgressEvent pe = new ProgressEvent();
+ pe.setFileName( f.getPath() );
+ pe.setError( IInstallationListener.ERROR,
+ "Sub theme installation failed: " + e.toString() );
+ iListener.installationCompleted( pe );
+ }
+ }
+
+ }
+
+ private Vector searchManifests( File aLocation )
+ {
+ // Create a FilenameFilter class for searching manifest (.dat) files
+ FilenameFilter filter = new FilenameFilter()
+ {
+ public boolean accept( File aDir, String aName )
+ {
+ if( aName.endsWith( MANIFEST_SUFFIX ) )
+ {
+ return true;
+ }
+ return false;
+ }
+ };
+
+ // List all manifest files in the directory and add them to
+ // the result vector
+ File[] files = aLocation.listFiles( filter );
+ Vector v = new Vector();
+ for( int i = 0; i < files.length; i++ )
+ {
+ v.add( files[ i ] );
+ }
+
+ return v;
+ }
+
+ }