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.util.Collection; 024 import java.util.HashMap; 025 import java.util.HashSet; 026 import java.util.LinkedList; 027 import java.util.Map; 028 import java.util.Set; 029 import java.util.concurrent.Semaphore; 030 import java.util.regex.Matcher; 031 import java.util.regex.Pattern; 032 033 import com.ochafik.io.ReadText; 034 035 036 public class Solution { 037 private static final boolean verbose = true; 038 039 public File solutionFile; 040 public Map<String, Project> idToProject; 041 public Set<File> allFiles = new HashSet<File>(10000); 042 043 static Pattern solutionIdPattern = Pattern.compile("Project\\(\"\\{[^}]+\\}\"\\) = \"([^\"]+)\", \"([^\"]+)\", [^{]+\\{([^}]+)\\}\"" + 044 ".*?ProjectSection\\(ProjectDependencies\\)(.*?)EndProjectSection", Pattern.MULTILINE 045 ); 046 047 static Pattern projectDependencyPattern = Pattern.compile("\\{[^}]+\\} = \\{([^}]+)\\}"); 048 049 static Pattern projectConfigsForSolutionConfigPattern = Pattern.compile("^\\s*\\{([^}]+)\\}\\.([^\\.]+)\\.ActiveCfg\\s*=\\s*(.*)\\s*$"); 050 public Solution(File solutionFile) { 051 this.solutionFile = solutionFile; 052 } 053 public void parse() throws Exception { 054 if (idToProject == null) { 055 idToProject = new HashMap<String, Project>(); 056 057 String solutionContent = ReadText.readText(solutionFile); 058 File solutionPath = solutionFile.getParentFile(); 059 060 for (Matcher solutionIdMatcher = solutionIdPattern.matcher(solutionContent.replace('\n', ' ')); solutionIdMatcher.find();) { 061 Project p = new Project(this, relFile(solutionPath, solutionIdMatcher.group(2)), solutionIdMatcher.group(1), solutionIdMatcher.group(3)); 062 for (Matcher depM = projectDependencyPattern.matcher(solutionIdMatcher.group(4)); depM.find();) 063 p.depsIds.add(depM.group(1)); 064 idToProject.put(p.id, p); 065 } 066 067 for (Matcher m = projectConfigsForSolutionConfigPattern.matcher(solutionContent); m.find();) { 068 String id = m.group(1), slnConfigName = m.group(2), projConfigName = m.group(3); 069 Project p = idToProject.get(id); 070 if (p == null) 071 continue; 072 073 p.activeConfigurationNameBySolutionConfigurationName.put(slnConfigName, projConfigName); 074 } 075 } 076 } 077 078 public String getName() { 079 return solutionFile == null ? null : solutionFile.getName().replaceAll("\\.[^.]+$", ""); 080 } 081 082 public void parseProjects(final FileFilter fileFilter) throws Exception { 083 parse(); 084 int nThreads = Runtime.getRuntime().availableProcessors() * 2; 085 if (verbose) 086 System.out.println("Parsing Solution: " + solutionFile.getName() + " (" + nThreads + " threads)"); 087 088 final Semaphore semaphore = new Semaphore(0); 089 final LinkedList<Project> projects = new LinkedList<Project>(idToProject.values()); 090 class Worker extends Thread { public void run() { 091 for (;;) { 092 try { 093 Project project = null; 094 synchronized (projects) { 095 if (projects.isEmpty()) 096 break; 097 098 project = projects.removeLast(); 099 } 100 if (verbose) { 101 synchronized (System.out) { 102 System.out.println("Parsing Project: " + project.name); 103 } 104 } 105 106 project.parse(fileFilter, false, Solution.this); 107 synchronized (allFiles) { 108 allFiles.addAll(project.files); 109 } 110 } catch (Exception ex) { 111 synchronized (System.err) { 112 ex.printStackTrace(System.err); 113 } 114 115 } 116 } 117 semaphore.release(); 118 }}; 119 for (int i = nThreads; i-- != 0;) 120 new Worker().start(); 121 122 semaphore.acquire(nThreads); 123 } 124 125 static File relFile(File base, String relPath) { 126 relPath = relPath.replace('\\', File.separatorChar).replace('/', File.separatorChar); 127 return new File(base, relPath); 128 } 129 public Collection<Project> getProjects() { 130 return idToProject.values(); 131 } 132 }