View Javadoc

1   /*
2   	Copyright (c) 2009 Olivier Chafik, All Rights Reserved
3   	
4   	This file is part of JNAerator (http://jnaerator.googlecode.com/).
5   	
6   	JNAerator is free software: you can redistribute it and/or modify
7   	it under the terms of the GNU General Public License as published by
8   	the Free Software Foundation, either version 3 of the License, or
9   	(at your option) any later version.
10  	
11  	JNAerator is distributed in the hope that it will be useful,
12  	but WITHOUT ANY WARRANTY; without even the implied warranty of
13  	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  	GNU General Public License for more details.
15  	
16  	You should have received a copy of the GNU General Public License
17  	along with JNAerator.  If not, see <http://www.gnu.org/licenses/>.
18  */
19  package com.ochafik.admin.visualstudio;
20  
21  import java.io.File;
22  import java.io.FileFilter;
23  import java.util.Collection;
24  import java.util.HashMap;
25  import java.util.HashSet;
26  import java.util.LinkedList;
27  import java.util.Map;
28  import java.util.Set;
29  import java.util.concurrent.Semaphore;
30  import java.util.regex.Matcher;
31  import java.util.regex.Pattern;
32  
33  import com.ochafik.io.ReadText;
34  
35  
36  public class Solution {
37  	private static final boolean verbose = true;
38  	
39  	public File solutionFile;
40  	public Map<String, Project> idToProject;
41  	public Set<File> allFiles = new HashSet<File>(10000);
42  
43  	static Pattern solutionIdPattern = Pattern.compile("Project\\(\"\\{[^}]+\\}\"\\) = \"([^\"]+)\", \"([^\"]+)\", [^{]+\\{([^}]+)\\}\"" +
44  		".*?ProjectSection\\(ProjectDependencies\\)(.*?)EndProjectSection", Pattern.MULTILINE
45  	);
46  
47  	static Pattern projectDependencyPattern = Pattern.compile("\\{[^}]+\\} = \\{([^}]+)\\}");
48  
49  	static Pattern projectConfigsForSolutionConfigPattern = Pattern.compile("^\\s*\\{([^}]+)\\}\\.([^\\.]+)\\.ActiveCfg\\s*=\\s*(.*)\\s*$");
50  	public Solution(File solutionFile) {
51  		this.solutionFile = solutionFile;
52  	}
53  	public void parse() throws Exception {
54  		if (idToProject == null) {
55  			idToProject = new HashMap<String, Project>();
56  			
57  			String solutionContent = ReadText.readText(solutionFile);
58  			File solutionPath = solutionFile.getParentFile();
59  			
60  			for (Matcher solutionIdMatcher = solutionIdPattern.matcher(solutionContent.replace('\n', ' ')); solutionIdMatcher.find();) {
61  				Project p = new Project(this, relFile(solutionPath, solutionIdMatcher.group(2)), solutionIdMatcher.group(1), solutionIdMatcher.group(3));
62  				for (Matcher depM = projectDependencyPattern.matcher(solutionIdMatcher.group(4)); depM.find();)
63  					p.depsIds.add(depM.group(1));
64  				idToProject.put(p.id, p);
65  			}
66  			
67  			for (Matcher m = projectConfigsForSolutionConfigPattern.matcher(solutionContent); m.find();) {
68  				String id = m.group(1), slnConfigName = m.group(2), projConfigName = m.group(3);
69  				Project p = idToProject.get(id);
70  				if (p == null)
71  					continue;
72  				
73  				p.activeConfigurationNameBySolutionConfigurationName.put(slnConfigName, projConfigName);
74  			}
75  		}
76  	}
77  	
78  	public String getName() {
79  		return solutionFile == null ? null : solutionFile.getName().replaceAll("\\.[^.]+$", "");
80  	}
81  	
82  	public void parseProjects(final FileFilter fileFilter) throws Exception {
83  		parse();
84  		int nThreads = Runtime.getRuntime().availableProcessors() * 2;
85  		if (verbose)
86  			System.out.println("Parsing Solution: " + solutionFile.getName() + " (" + nThreads + " threads)");
87  		
88  		final Semaphore semaphore = new Semaphore(0);
89  		final LinkedList<Project> projects = new LinkedList<Project>(idToProject.values());
90  		class Worker extends Thread { public void run() {
91  			for (;;) {
92  				try {
93  					Project project = null;
94  					synchronized (projects) {
95  						if (projects.isEmpty())
96  							break;
97  						
98  						project = projects.removeLast();
99  					}
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 }