trace/tracebuilder/com.nokia.tracebuilder/src/com/nokia/tracebuilder/engine/propertyfile/PropertyFileEngine.java
changeset 10 ed1c9f64298a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trace/tracebuilder/com.nokia.tracebuilder/src/com/nokia/tracebuilder/engine/propertyfile/PropertyFileEngine.java	Wed Jun 23 14:35:40 2010 +0300
@@ -0,0 +1,348 @@
+/*
+* Copyright (c) 2008 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:
+*
+* Property file management engine
+*
+*/
+package com.nokia.tracebuilder.engine.propertyfile;
+
+import java.io.File;
+import java.io.OutputStream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import com.nokia.tracebuilder.engine.TraceBuilderEngine;
+import com.nokia.tracebuilder.engine.TraceBuilderErrorMessages;
+import com.nokia.tracebuilder.engine.TraceBuilderGlobals;
+import com.nokia.tracebuilder.engine.TraceBuilderErrorCodes.TraceBuilderErrorCode;
+import com.nokia.tracebuilder.engine.project.ProjectEngine;
+import com.nokia.tracebuilder.file.FileUtils;
+import com.nokia.tracebuilder.model.TraceBuilderException;
+import com.nokia.tracebuilder.model.TraceConstantTable;
+import com.nokia.tracebuilder.model.TraceConstantTableEntry;
+import com.nokia.tracebuilder.model.TraceModel;
+import com.nokia.tracebuilder.model.TraceModelListener;
+import com.nokia.tracebuilder.model.TraceObject;
+import com.nokia.tracebuilder.model.TraceProcessingListener;
+import com.nokia.tracebuilder.project.ProjectUtils;
+import com.nokia.tracebuilder.source.SourceConstants;
+
+/**
+ * Property file management engine
+ * 
+ */
+public final class PropertyFileEngine extends TraceBuilderEngine implements
+		TraceModelListener, TraceProcessingListener {
+
+	/**
+	 * Trace model
+	 */
+	private TraceModel model;
+
+	/**
+	 * Model processing flag prevents unnecessary saves
+	 */
+	private boolean processing;
+
+	/**
+	 * Backup created flag. This is initially set to false and when backup is
+	 * created, changes to true
+	 */
+	private boolean backupCreated;
+
+	/**
+	 * Constructor
+	 * 
+	 * @param model
+	 *            the trace model
+	 */
+	public PropertyFileEngine(TraceModel model) {
+		this.model = model;
+		model.addModelListener(this);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.nokia.tracebuilder.engine.TraceBuilderEngine#projectOpened()
+	 */
+	@Override
+	public void projectOpened() {
+		TracePropertyFile propertyFile = model
+				.getExtension(TracePropertyFile.class);
+		if (propertyFile == null) {
+			String fileName = null;
+			try {
+				fileName = ProjectUtils.getLocationForFile(model,
+						ProjectEngine.traceFolderName,
+						PropertyFileConstants.PROPERTY_FILE_NAME, false);
+			} catch (TraceBuilderException e) {
+				// Model should always be open when traceProjectOpened is
+				// called
+			}
+			if (fileName != null) {
+				propertyFile = parsePropertyFile(fileName);
+				// Backup flag is reset when model is opened
+				backupCreated = false;
+			}
+		}
+		if (propertyFile == null) {
+			String msg = Messages
+					.getString("PropertyFileEngine.FailedToAttachFile"); //$NON-NLS-1$
+			TraceBuilderGlobals.getEvents().postErrorMessage(msg, null, true);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.nokia.tracebuilder.engine.TraceBuilderEngine#projectClosing()
+	 */
+	@Override
+	public void projectClosed() {
+		model.removeExtensions(TracePropertyFile.class);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.nokia.tracebuilder.engine.TraceBuilderEngine#exportProject()
+	 */
+	@Override
+	public void exportProject() {
+	}
+
+	/**
+	 * Parses the property file
+	 * 
+	 * @param fileName
+	 *            the file path
+	 * @return the property file
+	 */
+	private TracePropertyFile parsePropertyFile(String fileName) {
+		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+		factory.setValidating(false);
+		DocumentBuilder builder;
+		TracePropertyFile propertyFile = null;
+		try {
+			builder = factory.newDocumentBuilder();
+			File file = new File(fileName);
+			if (file.exists()) {
+				try {
+					PropertyFileParser parser = new PropertyFileParser(model,
+							fileName, builder);
+					parser.parse();
+					propertyFile = new TracePropertyFile(file.getParent(),
+							parser.getDocument());
+					propertyFile.setProperties(parser.getGroupProperties(),
+							parser.getTraceProperties());
+				} catch (TraceBuilderException e) {
+					// Problem parsing document -> Backup and create new
+					TraceBuilderGlobals.getEvents().postError(e);
+					createBackup(fileName);
+				}
+			}
+			if (propertyFile == null) {
+				propertyFile = new TracePropertyFile(file.getParent(), builder
+						.newDocument());
+			}
+			model.addExtension(propertyFile);
+		} catch (ParserConfigurationException e) {
+		}
+		return propertyFile;
+	}
+
+	/**
+	 * Writes the property file
+	 */
+	private void writePropertyFile() {
+		if (!processing) {
+			TracePropertyFile propertyFile = model
+					.getExtension(TracePropertyFile.class);
+			if (propertyFile != null) {
+				// Backup flag is checked. If not set, a backup is created and
+				// the flag is set. The flag is reset when project is re-opened
+				String path = propertyFile.getAbsolutePath();
+				if (!backupCreated) {
+					createBackup(path);
+					backupCreated = true;
+				}
+				try {
+					// Uses XML API to write the property file
+					OutputStream fos = FileUtils.createOutputStream(new File(
+							path));
+					Transformer transformer = TransformerFactory.newInstance()
+							.newTransformer();
+					transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
+					transformer.transform(new DOMSource(propertyFile
+							.getDocument()), new StreamResult(fos));
+					fos.close();
+					propertyFile.postFileWrittenEvent(path);
+				} catch (Exception e) {
+					String msg = TraceBuilderErrorMessages.getErrorMessage(
+							TraceBuilderErrorCode.CANNOT_WRITE_PROJECT_FILE,
+							null);
+					TraceBuilderGlobals.getEvents().postErrorMessage(msg, e, true);
+				}
+			}
+		}
+	}
+
+	/**
+	 * Creates a backup of the property file
+	 * 
+	 * @param path
+	 *            the file to be backed up
+	 */
+	private void createBackup(String path) {
+		boolean backup = false;
+		File file = new File(path);
+		if (file.exists()) {
+			boolean allexist = true;
+			// Checks the existing backup files and renames the old file to
+			// largest available number starting from 0
+			File f = null;
+			for (int i = 0; i < PropertyFileConstants.BACKUP_COUNT && allexist; i++) {
+				f = new File(path + i + PropertyFileConstants.BACKUP_EXTENSION);
+				if (!f.exists()) {
+					backup = FileUtils.copyFile(file, f);
+					allexist = false;
+				}
+			}
+			if (allexist) {
+				// If all backups from 0 to 9 exist, the old ones are moved
+				// back 1 step. The new file is renamed to *9.h
+				for (int i = 0; i < PropertyFileConstants.BACKUP_COUNT; i++) {
+					f = new File(path + i
+							+ PropertyFileConstants.BACKUP_EXTENSION);
+					if (i == 0) {
+						f.delete();
+					} else {
+						f.renameTo(new File(path + (i - 1)
+								+ PropertyFileConstants.BACKUP_EXTENSION));
+					}
+				}
+				f = new File(path + PropertyFileConstants.LAST_BACKUP);
+				backup = FileUtils.copyFile(file, f);
+			}
+			if (f != null && backup) {
+				String msg = Messages
+						.getString("PropertyFileEngine.PropertyFileBackUpPrefix") //$NON-NLS-1$
+						+ FileUtils.convertSeparators(
+								SourceConstants.FORWARD_SLASH_CHAR, f
+										.getAbsolutePath(), false);
+				TraceBuilderGlobals.getEvents().postInfoMessage(msg, null);
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.nokia.tracebuilder.model.TraceModelListener#
+	 *      objectAdded(com.nokia.tracebuilder.model.TraceObject,
+	 *      com.nokia.tracebuilder.model.TraceObject)
+	 */
+	public void objectAdded(TraceObject owner, TraceObject object) {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.nokia.tracebuilder.model.TraceModelListener#
+	 *      objectCreationComplete(com.nokia.tracebuilder.model.TraceObject)
+	 */
+	public void objectCreationComplete(TraceObject object) {
+		if (model.isValid()) {
+			if (object instanceof TraceConstantTable
+					|| object instanceof TraceConstantTableEntry) {
+				TracePropertyFile propertyFile = model
+						.getExtension(TracePropertyFile.class);
+				if (propertyFile != null) {
+					propertyFile.addElement(object);
+					writePropertyFile();
+				}
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.nokia.tracebuilder.model.TraceModelListener#
+	 *      objectRemoved(com.nokia.tracebuilder.model.TraceObject,
+	 *      com.nokia.tracebuilder.model.TraceObject)
+	 */
+	public void objectRemoved(TraceObject owner, TraceObject object) {
+		if (model.isValid()) {
+			if (object instanceof TraceConstantTable
+					|| object instanceof TraceConstantTableEntry) {
+				TracePropertyFile propertyFile = model
+						.getExtension(TracePropertyFile.class);
+				if (propertyFile != null) {
+					propertyFile.removeElement(object);
+					writePropertyFile();
+				}
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.nokia.tracebuilder.model.TraceModelListener#
+	 *      propertyUpdated(com.nokia.tracebuilder.model.TraceObject, int)
+	 */
+	public void propertyUpdated(TraceObject object, int property) {
+		if (object.isComplete()
+				&& (object instanceof TraceConstantTable || object instanceof TraceConstantTableEntry)) {
+			TracePropertyFile propertyFile = model
+					.getExtension(TracePropertyFile.class);
+			if (propertyFile != null) {
+				propertyFile.updateElement(object);
+				writePropertyFile();
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.nokia.tracebuilder.model.TraceProcessingListener#processingComplete(boolean)
+	 */
+	public void processingComplete(boolean changed) {
+		processing = false;
+		if (changed) {
+			writePropertyFile();
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.nokia.tracebuilder.model.TraceProcessingListener#processingStarted()
+	 */
+	public void processingStarted() {
+		processing = true;
+	}
+
+}