001 /* 002 Copyright (c) 2009 Olivier Chafik, All Rights Reserved 003 004 This file is part of JNAerator (http://jnaerator.googlecode.com/). 005 006 JNAerator is free software: you can redistribute it and/or modify 007 it under the terms of the GNU General Public License as published by 008 the Free Software Foundation, either version 3 of the License, or 009 (at your option) any later version. 010 011 JNAerator is distributed in the hope that it will be useful, 012 but WITHOUT ANY WARRANTY; without even the implied warranty of 013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 GNU General Public License for more details. 015 016 You should have received a copy of the GNU General Public License 017 along with JNAerator. If not, see <http://www.gnu.org/licenses/>. 018 */ 019 package com.ochafik.admin.visualstudio; 020 021 import java.io.File; 022 import java.io.FileFilter; 023 import java.io.IOException; 024 import java.util.ArrayList; 025 import java.util.Arrays; 026 import java.util.Collections; 027 import java.util.HashMap; 028 import java.util.List; 029 import java.util.Map; 030 import java.util.TreeSet; 031 import static com.ochafik.admin.visualstudio.VisualStudioUtils.*; 032 033 import javax.xml.xpath.XPathExpressionException; 034 035 import org.w3c.dom.Document; 036 import org.w3c.dom.Node; 037 038 import com.ochafik.xml.XMLUtils; 039 import com.ochafik.xml.XPathUtils; 040 041 public class Project implements Comparable<Project> { 042 public final Solution solution; 043 public File projectFile; 044 public String name, id; 045 public List<String> depsIds = new ArrayList<String>(); 046 public Map<String, String> activeConfigurationNameBySolutionConfigurationName = new HashMap<String, String>(); 047 048 public Map<String, Configuration> configurations = new HashMap<String, Configuration>(); 049 public Map<File, FileConfiguration> fileConfigurations = new HashMap<File, FileConfiguration>(); 050 public List<File> files = new ArrayList<File>(); 051 052 public Project(Solution solution, File projectFile, String name, String id) { 053 this.solution = solution; 054 this.projectFile = projectFile; 055 this.name = name; 056 this.id = id; 057 } 058 public int compareTo(Project o) { 059 return name.compareTo(o.name); 060 } 061 062 String resolve(String s, Configuration configuration) { 063 String res = resolveVariables(s, solution, this, configuration); 064 return res == null || res.length() == 0 ? null : res; 065 } 066 067 public String resolveStringByXPath(String xPathString, Object source, Configuration configuration) throws XPathExpressionException { 068 return resolve(XPathUtils.findStringByXPath(xPathString, source), configuration); 069 } 070 @SuppressWarnings("unchecked") 071 public List<String> resolveListByXPath(String xPathString, Object source, String separatorPattern, Configuration configuration) throws XPathExpressionException { 072 String s = resolve(XPathUtils.findStringByXPath(xPathString, source), configuration); 073 return s == null ? Collections.EMPTY_LIST : Arrays.asList(s.split(separatorPattern)); 074 } 075 public TreeSet<String> resolveSetByXPath(String xPathString, Object source, String separatorPattern, Configuration configuration) throws XPathExpressionException { 076 return new TreeSet<String>(resolveListByXPath(xPathString, source, separatorPattern, configuration)); 077 } 078 079 Configuration parseConfiguration(Node configNode) throws XPathExpressionException { 080 Configuration config = new Configuration(); 081 config.name = resolve(XPathUtils.findStringByXPath("@Name", configNode), config); 082 if (config.name == null) 083 return null; 084 085 config.outputDirectory = resolve(XPathUtils.findStringByXPath("@OutputDirectory", configNode), config); 086 087 Node compilerTool = XPathUtils.findNodeByXPath("Tool[@Name='VCCLCompilerTool']", configNode); 088 if (compilerTool != null) { 089 config.includes = resolveListByXPath("@AdditionalIncludeDirectories", compilerTool, ";", config); 090 config.preprocessorDefinitions = resolveSetByXPath("@PreprocessorDefinitions", compilerTool, ";", config); 091 } 092 config.outputFile = resolve(XPathUtils.findStringByXPath("Tool[@Name='VCLinkerTool']/@OutputFile", configNode), config); 093 /*if (config.outputFile == null) 094 config.outputFile = name + ".dll";*/ 095 096 return config; 097 } 098 099 public void parse(FileFilter fileFilter, boolean parseFileConfigurations, Solution solution) throws Exception { 100 if (!projectFile.exists() || !projectFile.isFile()) 101 throw new IOException("Cannot find project file " + projectFile); 102 103 Document document = XMLUtils.readXML(projectFile); 104 File projectPath = projectFile.getParentFile(); 105 106 for (Node configurationNode : XPathUtils.findNodesIterableByXPath("VisualStudioProject/Configurations/Configuration", document)) { 107 Configuration config = parseConfiguration(configurationNode); 108 if (config != null) 109 configurations.put(config.name, config); 110 } 111 for (Node fileNode : XPathUtils.findNodesIterableByXPath("//Files//File", document)) { 112 String relativePath = resolveStringByXPath("@RelativePath", fileNode, null); 113 if (relativePath == null) 114 continue; 115 116 File file = relFile(projectPath, relativePath); 117 if (fileFilter != null && !fileFilter.accept(file)) 118 continue; 119 120 files.add(file); 121 122 if (parseFileConfigurations) { 123 FileConfiguration fileConfiguration = new FileConfiguration(); 124 fileConfiguration.file = file; 125 fileConfigurations.put(file, fileConfiguration); 126 for (Node fileConfigurationNode : XPathUtils.findNodesIterableByXPath("FileConfiguration", fileNode)) { 127 Configuration config = parseConfiguration(fileConfigurationNode); 128 if (config != null) 129 fileConfiguration.configurations.put(config.name, config); 130 } 131 } 132 } 133 } 134 135 static File relFile(File base, String relPath) { 136 relPath = relPath.replace('\\', File.separatorChar).replace('/', File.separatorChar); 137 return new File(base, relPath); 138 } 139 }