tracefw/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/engine/header/HeaderEngine.java
changeset 56 aa2539c91954
parent 54 a151135b0cf9
child 60 e54443a6878c
child 62 1c2bb2fc7c87
equal deleted inserted replaced
54:a151135b0cf9 56:aa2539c91954
     1 /*
       
     2 * Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 * Header engine manages the trace header file that is included into source code
       
    17 *
       
    18 */
       
    19 package com.nokia.tracecompiler.engine.header;
       
    20 
       
    21 import java.io.File;
       
    22 import java.io.IOException;
       
    23 import java.util.ArrayList;
       
    24 import java.util.Iterator;
       
    25 
       
    26 import com.nokia.tracecompiler.engine.LocationListBase;
       
    27 import com.nokia.tracecompiler.engine.LocationProperties;
       
    28 import com.nokia.tracecompiler.engine.TraceCompilerEngineBase;
       
    29 import com.nokia.tracecompiler.engine.TraceCompilerEngineEvents;
       
    30 import com.nokia.tracecompiler.engine.TraceCompilerEngineGlobals;
       
    31 import com.nokia.tracecompiler.engine.TraceCompilerEngineErrorCodes.TraceCompilerErrorCode;
       
    32 import com.nokia.tracecompiler.engine.project.ProjectEngine;
       
    33 import com.nokia.tracecompiler.file.FileCompareOutputStream;
       
    34 import com.nokia.tracecompiler.model.Trace;
       
    35 import com.nokia.tracecompiler.model.TraceCompilerException;
       
    36 import com.nokia.tracecompiler.model.TraceGroup;
       
    37 import com.nokia.tracecompiler.model.TraceModel;
       
    38 import com.nokia.tracecompiler.plugin.TraceHeaderContribution;
       
    39 import com.nokia.tracecompiler.plugin.TraceHeaderContribution.TraceHeaderContributionType;
       
    40 import com.nokia.tracecompiler.project.ProjectUtils;
       
    41 import com.nokia.tracecompiler.project.TraceProjectAPI;
       
    42 import com.nokia.tracecompiler.source.SourceUtils;
       
    43 
       
    44 /**
       
    45  * Header engine manages the trace header file that is included into source
       
    46  * code. This implements the plug-in interface to get notifications about
       
    47  * project file opening and closing
       
    48  * 
       
    49  */
       
    50 public final class HeaderEngine extends TraceCompilerEngineBase {
       
    51 
       
    52 	/**
       
    53 	 * Trace model
       
    54 	 */
       
    55 	private TraceModel model;
       
    56 
       
    57 	/**
       
    58 	 * Constructor
       
    59 	 * 
       
    60 	 * @param model
       
    61 	 *            trace model
       
    62 	 */
       
    63 	public HeaderEngine(TraceModel model) {
       
    64 		this.model = model;
       
    65 	}
       
    66 
       
    67 	/*
       
    68 	 * (non-Javadoc)
       
    69 	 * 
       
    70 	 * @see com.nokia.tracecompiler.engine.TraceCompilerEngine#projectOpened()
       
    71 	 */
       
    72 	@Override
       
    73 	public void projectOpened() {
       
    74 		TraceHeader header = model.getExtension(TraceHeader.class);
       
    75 		if (header == null) {
       
    76 			String fileName = null;
       
    77 			try {
       
    78 				fileName = ProjectUtils.getLocationForFile(model,
       
    79 						ProjectEngine.traceFolderName,
       
    80 						HeaderConstants.TRACE_HEADER_NAME, false);
       
    81 			} catch (TraceCompilerException e) {
       
    82 				// Model should always be open when traceProjectOpened is called
       
    83 			}
       
    84 			if (fileName != null) {
       
    85 				header = new TraceHeader(fileName, false);
       
    86 				model.addExtension(header);
       
    87 			} else {
       
    88 				String msg = Messages
       
    89 						.getString("HeaderEngine.FailedToAttachHeader"); //$NON-NLS-1$
       
    90 				TraceCompilerEngineGlobals.getEvents().postErrorMessage(msg, null, true);
       
    91 			}
       
    92 		}
       
    93 	}
       
    94 
       
    95 	/*
       
    96 	 * (non-Javadoc)
       
    97 	 * 
       
    98 	 * @see com.nokia.tracecompiler.engin.TraceCompilererEngine#projectClosing()
       
    99 	 */
       
   100 	@Override
       
   101 	public void projectClosed() {
       
   102 		model.removeExtensions(TraceHeader.class);
       
   103 	}
       
   104 
       
   105 	/**
       
   106 	 * Gets the name for the trace header file based on given source
       
   107 	 * 
       
   108 	 * @param sourceFile
       
   109 	 *            the source file name
       
   110 	 * @return the header file name
       
   111 	 */
       
   112 	public String getHeaderFileName(String sourceFile) {
       
   113 		String retval = null;
       
   114 		if (model != null) {
       
   115 			// The header file name is the source file name with extension
       
   116 			// replaced by Traces.h
       
   117 			File f = new File(sourceFile);
       
   118 			retval = removeFileExtension(f.getName())
       
   119 					+ HeaderConstants.TRACE_HEADER_EXTENSION;
       
   120 		}
       
   121 		return retval;
       
   122 	}
       
   123 
       
   124 	/*
       
   125 	 * (non-Javadoc)
       
   126 	 * 
       
   127 	 * @see com.nokia.tracecompiler.engi.TraceCompilerlerEngine#projectExporting()
       
   128 	 */
       
   129 	@Override
       
   130 	public void exportProject() throws TraceCompilerException {
       
   131 		if (model.isValid() && model.hasTraces()) {
       
   132 			TraceHeader header = model.getExtension(TraceHeader.class);
       
   133 			if (header != null) {
       
   134 				// Headers for each source are written first
       
   135 				String path = header.getPath();
       
   136 				ArrayList<String> fileNames = new ArrayList<String>();
       
   137 				collectSourceFilesFromTraces(fileNames);
       
   138 				for (String fileName : fileNames) {
       
   139 					String target = path + File.separator + fileName;
       
   140 					writeHeaderFile(target);
       
   141 				}
       
   142 				// The main header is written after everything else succeeds
       
   143 				writeMainHeaderFile(header);
       
   144 			}
       
   145 		}
       
   146 	}
       
   147 
       
   148 	/**
       
   149 	 * Collects the source file names from traces
       
   150 	 * 
       
   151 	 * @param fileNames
       
   152 	 *            the file names
       
   153 	 */
       
   154 	private void collectSourceFilesFromTraces(ArrayList<String> fileNames) {
       
   155 		for (TraceGroup group : model) {
       
   156 			for (Trace trace : group) {
       
   157 				Iterator<LocationListBase> itr = trace
       
   158 						.getExtensions(LocationListBase.class);
       
   159 				while (itr.hasNext()) {
       
   160 					LocationListBase base = itr.next();
       
   161 					for (LocationProperties loc : base) {
       
   162 						String locFileName = loc.getFileName();
       
   163 						if (locFileName != null) {
       
   164 							addFileToList(fileNames, locFileName);
       
   165 						}
       
   166 					}
       
   167 				}
       
   168 			}
       
   169 		}
       
   170 	}
       
   171 
       
   172 	/**
       
   173 	 * Adds a file to list if it does not exist
       
   174 	 * 
       
   175 	 * @param fileNames
       
   176 	 *            the list
       
   177 	 * @param locFileName
       
   178 	 *            the file
       
   179 	 */
       
   180 	private void addFileToList(ArrayList<String> fileNames, String locFileName) {
       
   181 		locFileName = removeFileExtension(locFileName);
       
   182 		if (!fileNames.contains(locFileName)) {
       
   183 			fileNames.add(locFileName);
       
   184 		}
       
   185 	}
       
   186 
       
   187 	/**
       
   188 	 * Removes the file extension from file name
       
   189 	 * 
       
   190 	 * @param fileName
       
   191 	 *            the file name
       
   192 	 * @return name without extension
       
   193 	 */
       
   194 	private String removeFileExtension(String fileName) {
       
   195 		int index = fileName.lastIndexOf('.');
       
   196 		int sep1 = fileName.lastIndexOf('/');
       
   197 		int sep2 = fileName.lastIndexOf('\\');
       
   198 		if (index > sep1 && index > sep2) {
       
   199 			fileName = fileName.substring(0, index);
       
   200 		}
       
   201 		return fileName;
       
   202 	}
       
   203 
       
   204 	/**
       
   205 	 * Writes the header to given target
       
   206 	 * 
       
   207 	 * @param target
       
   208 	 *            the target file
       
   209 	 * @throws TraceCompilerException
       
   210 	 *             if writing fails
       
   211 	 */
       
   212 	private void writeHeaderFile(String target) throws TraceCompilerException {
       
   213 		// The TraceHeader stored into the model is not used when writing
       
   214 		// headers, since a separate header is written for each source file
       
   215 		TraceHeader header = new TraceHeader(target, true);
       
   216 		try {
       
   217 			header.setOwner(model);
       
   218 			TraceHeaderWriter writer = new TraceHeaderWriter(header);
       
   219 			TraceCompilerEngineEvents events = TraceCompilerEngineGlobals.getEvents();
       
   220 			if (writer.write()) {
       
   221 				header.postFileWrittenEvent(header.getAbsolutePath());
       
   222 			} else {
       
   223 				String msg = Messages
       
   224 						.getString("HeaderEngine.TraceHeaderNotChangedPrefix"); //$NON-NLS-1$
       
   225 				events.postInfoMessage(msg + header.getAbsolutePath(), null);
       
   226 			}
       
   227 		} finally {
       
   228 			// The header owner must be reset to null, since that makes
       
   229 			// unregisters it from the model
       
   230 			header.setOwner(null);
       
   231 		}
       
   232 	}
       
   233 
       
   234 	/**
       
   235 	 * Writes the main header file to given target
       
   236 	 * 
       
   237 	 * @param header
       
   238 	 *            the header
       
   239 	 * @throws TraceCompilerException
       
   240 	 *             if writing fails
       
   241 	 */
       
   242 	private void writeMainHeaderFile(TraceHeader header)
       
   243 			throws TraceCompilerException {
       
   244 		// The TraceHeader stored into the model is not used when writing
       
   245 		// headers, since a separate header is written for each source file
       
   246 		TraceCompilerEngineEvents events = TraceCompilerEngineGlobals.getEvents();
       
   247 		String path = header.getAbsolutePath();
       
   248 		try {
       
   249 			if (writeMainHeader(path)) {
       
   250 				header.postFileWrittenEvent(path);
       
   251 			} else {
       
   252 				String msg = Messages
       
   253 						.getString("HeaderEngine.TraceHeaderNotChangedPrefix"); //$NON-NLS-1$
       
   254 				events.postInfoMessage(msg + path, null);
       
   255 			}
       
   256 		} catch (IOException e) {
       
   257 			throw new TraceCompilerException(
       
   258 					TraceCompilerErrorCode.CANNOT_WRITE_PROJECT_FILE, e);
       
   259 		}
       
   260 	}
       
   261 
       
   262 	/**
       
   263 	 * Writes the main header to given target
       
   264 	 * 
       
   265 	 * @param target
       
   266 	 *            the target
       
   267 	 * @return true if written, false if the file already had the same content
       
   268 	 * @throws IOException
       
   269 	 *             if writing fails
       
   270 	 */
       
   271 	private boolean writeMainHeader(String target) throws IOException {
       
   272 		File f = new File(target);
       
   273 		FileCompareOutputStream stream = new FileCompareOutputStream(f);
       
   274 		String licence = TraceCompilerEngineGlobals.getDefaultLicence(true);
       
   275 		if (licence != null) {
       
   276 			stream.write(licence.getBytes());
       
   277 		}
       
   278 		stream.write(SourceUtils.createHeaderGuard(f.getName()).getBytes());
       
   279 		TraceProjectAPI api = model.getExtension(TraceProjectAPI.class);
       
   280 		if (api instanceof TraceHeaderContribution) {
       
   281 			String[] content = ((TraceHeaderContribution) api)
       
   282 					.getContribution(TraceHeaderContributionType.MAIN_HEADER_CONTENT);
       
   283 			if (content != null && content.length == 1) {
       
   284 				stream.write(content[0].getBytes());
       
   285 			}
       
   286 		}
       
   287 		return stream.writeFile();
       
   288 	}
       
   289 }