buildframework/helium/sf/java/sysdef/src/com/nokia/helium/sysdef/ant/taskdefs/CreatePackageMappingTask.java
/*
* Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "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:
*
*/
package com.nokia.helium.sysdef.ant.taskdefs;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.DirSet;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceCollection;
import com.nokia.helium.sysdef.PackageMap;
import com.nokia.helium.sysdef.PackageMapParsingException;
/**
* Create a ini file which stores the mapping between packages under a checked out
* location and where they should be located under the environment.
*
* Format of the generated file:
* <pre>
* #DO NOT EDIT - File generated automatically
* #Thu Mar 25 15:52:03 EET 2010
* source\\location\\of\\package=EPOCROOT\\root\\layer\\package
* E\:\\scm\\package=E:\sdk\root\layer\package
* </pre>
*
* Example:
* <pre>
* <hlm:createPackageMapping epocroot="E:\sdk" destFile="E:\sdk\mapping.ini" >
* <fileset dir="E:\scm" includes="**/package_definition.xml">
* </hlm:createPackageMapping>
* </pre>
* <pre>
* <hlm:createPackageMapping epocroot="E:\sdk" destFile="E:\sdk\mapping.ini"
* filterDirSet="ado.filter.dir" >
* <fileset dir="E:\scm" includes="**/package_definition.xml">
* </hlm:createPackageMapping>
* </pre>
*
* The outcome will be the mapping file E:\sdk\mapping.ini.
*
* @ant.task name="createPackageMapping" category="Sysdef"
*/
public class CreatePackageMappingTask extends Task {
public static final String PACKAGE_DEFINITION_FILENAME = "package_definition.xml";
public static final String PACKAGE_MAP_FILENAME = "package_map.xml";
private List<ResourceCollection> resourceCollections = new ArrayList<ResourceCollection>();
private boolean failOnError = true;
private Map<File, File> pkgMapping = new HashMap<File, File>();
private File epocroot;
private File destFile;
private String filteredDirSet;
/**
* Populate the pkgMapping based on the packages found.
* @param pkgMapFile a pointer to a package map file.
* @throws PackageMapParsingException
*/
protected void retrievePackageMapping(File pkgMapFile, List<File> filterDirs) throws PackageMapParsingException {
PackageMap parser = new PackageMap(pkgMapFile);
log("parent file: " + pkgMapFile.getParentFile(), Project.MSG_DEBUG);
log("parent file: " + getEpocroot() + parser.getRoot() + "/" + parser.getLayer() +
"/" + pkgMapFile.getParentFile().getName(), Project.MSG_DEBUG);
if (filterDirs == null) {
pkgMapping.put(pkgMapFile.getParentFile(),
new File(getEpocroot(), parser.getRoot() + "/" + parser.getLayer() +
"/" + pkgMapFile.getParentFile().getName()));
} else {
for (File dir : filterDirs) {
if (pkgMapFile.getParentFile().equals(dir)) {
pkgMapping.put(pkgMapFile.getParentFile(),
new File(getEpocroot(), parser.getRoot() + "/" + parser.getLayer() +
"/" + pkgMapFile.getParentFile().getName()));
return;
}
}
}
}
@SuppressWarnings("unchecked")
protected List<File> getFilterDir() throws IOException {
if (filteredDirSet != null) {
Hashtable<String, Object> references = getProject().getReferences();
Object filteredDirSetObject = references.get(filteredDirSet);
if (filteredDirSetObject != null) {
if (!(filteredDirSetObject instanceof DirSet)) {
throw new BuildException("filteredDirSet is not of type "
+ "dirset");
}
List<File> fileList = new ArrayList<File>();
DirSet dset = (DirSet)filteredDirSetObject;
DirectoryScanner ds = dset.getDirectoryScanner(getProject());
String[] includedFiles = ds.getIncludedDirectories();
for (String file : includedFiles) {
fileList.add(new File(ds.getBasedir(), file));
}
return fileList;
} else {
throw new BuildException("Id '" + filteredDirSet + "' doesn't reference a type.");
}
}
return null;
}
/**
* Generates the ini file.
* @throws FileNotFoundException in case of missing file.
* @throws IOException in case of error while generating the file.
*/
@SuppressWarnings("unchecked")
protected void createIniFile(File mappingFile) throws IOException {
List<File> filterDirs = getFilterDir();
for (ResourceCollection rc : resourceCollections) {
Iterator<Resource> ri = (Iterator<Resource>)rc.iterator();
while (ri.hasNext()) {
Resource resource = ri.next();
File pkgFile = new File(resource.toString()); // toString is representing the abs path
log("Checking " + pkgFile.getName(), Project.MSG_DEBUG);
if (pkgFile.getName().equalsIgnoreCase(PACKAGE_DEFINITION_FILENAME)
&& pkgFile.exists()) {
File pkgMapFile = new File(pkgFile.getParentFile(),
PACKAGE_MAP_FILENAME);
log("Checking " + PACKAGE_MAP_FILENAME + " file: "
+ pkgMapFile, Project.MSG_DEBUG);
if (pkgMapFile.exists()) {
log("Found package: " + pkgFile);
try {
retrievePackageMapping(pkgMapFile, filterDirs);
} catch (PackageMapParsingException e) {
log(e.getMessage(), Project.MSG_ERR);
if (shouldFailOnError()) {
throw new BuildException(e.getMessage(), e);
}
}
} else if (!(new File(pkgFile.getParentFile(),
"../../" + PACKAGE_MAP_FILENAME).exists())) {
log("Could not find: " + pkgMapFile.getAbsolutePath(),
Project.MSG_ERR);
if (shouldFailOnError()) {
throw new BuildException("Package under "
+ pkgMapFile.getParent() +
" is invalid because of the following missing file: "
+ pkgMapFile.getAbsolutePath());
}
}
} else if (pkgFile.getName().equalsIgnoreCase(PACKAGE_DEFINITION_FILENAME)
&& !pkgFile.exists()) {
log("Could not find package definition file: "
+ pkgFile.getAbsolutePath(), Project.MSG_ERR);
if (shouldFailOnError()) {
throw new BuildException("Package under " + pkgFile.getParent() +
" is invalid because of the following missing file: " + pkgFile.getAbsolutePath());
}
} else {
log("Ignoring file: " + pkgFile.getAbsolutePath(), Project.MSG_VERBOSE);
}
}
}
Properties properties = new Properties();
for (File key : pkgMapping.keySet()) {
log("Adding package mapping entry for: " + key.getAbsolutePath(),
Project.MSG_DEBUG);
String replacedKey = key.getAbsolutePath().replace('\\', '/');
String replacedValue =
pkgMapping.get(key).getAbsolutePath().replace('\\', '/');
properties.setProperty(replacedKey,
replacedValue);
}
if (properties.isEmpty() && filteredDirSet != null) {
log("Empty mapping after filtering (filter: " +
filteredDirSet + ")", Project.MSG_WARN);
}
log("Creating " + mappingFile);
FileOutputStream fos = new FileOutputStream(mappingFile);
properties.store(fos, "DO NOT EDIT - File generated automatically");
fos.close();
}
/**
* {@inheritDoc}
*/
public void execute() {
if (getEpocroot() == null) {
throw new BuildException("The 'epocroot' attribute is not defined");
}
if (destFile == null) {
throw new BuildException("The 'destFile' attribute is not defined");
}
try {
createIniFile(destFile);
} catch (FileNotFoundException e) {
throw new BuildException("Error generating the output file: " + e.getMessage(), e);
} catch (IOException e) {
throw new BuildException("Error generating the output file: " + e.getMessage(), e);
}
}
/**
* Defines quality dir set location
* @param qualityDir - directory fileset which needs to be compared
* with sysdef path and map it for quality targets to use it.
* @ant.required
*/
public void setFilterDirSet(String filterDir) {
filteredDirSet = filterDir;
}
/**
* Defines epocroot location
* @param epocroot
* @ant.required
*/
public void setEpocroot(File epocroot) {
this.epocroot = epocroot;
}
/**
* Get epocroot.
* @return epocroot location
*/
public File getEpocroot() {
return epocroot;
}
/**
* Shall the task fails in case of error.
* @return
*/
public boolean shouldFailOnError() {
return failOnError;
}
/**
* Defines if the task should fail in case of error.
* @param failOnError
* @ant.not-required Default true
*/
public void setFailOnError(boolean failOnError) {
this.failOnError = failOnError;
}
/**
* Defines the location of the generated INI file.
* @param destFile
* @ant.required
*/
public void setDestFile(File destFile) {
this.destFile = destFile;
}
/**
* Get the destFile.
* @return the destination file wanted.
*/
public File getDestFile() {
return destFile;
}
/**
* Support of nested resource collection like path or fileset.
* Those nested element should define where to find the
* packages.
* @param resourceCollection
*/
public void add(ResourceCollection resourceCollection) {
resourceCollections.add(resourceCollection);
}
}