package org.objectstyle.wolips.eomodeler.factories; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.objectstyle.woenvironment.plist.PropertyListParserException; import org.objectstyle.woenvironment.plist.SimpleParserDataStructureFactory; import org.objectstyle.woenvironment.plist.WOLPropertyListSerialization; import org.objectstyle.wolips.baseforplugins.util.StringUtils; import org.objectstyle.wolips.eomodeler.core.model.AbstractManifestEOModelGroupFactory; import org.objectstyle.wolips.eomodeler.core.model.ManifestSearchFolder; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class IDEAProjectEOModelGroupFactory extends AbstractManifestEOModelGroupFactory { @Override public List<ManifestSearchFolder> getSearchFolders(File selectedModelFolder) throws IOException { //System.out.println("IDEAProjectEOModelGroupFactory.getSearchFolders: Looking for IDEA projects ..."); Set<ManifestSearchFolder> searchFolders = null; Set<File> ideaProjectFiles = new LinkedHashSet<File>(); try { IDEAProjectEOModelGroupFactory.findIdeaProjectFilesInFolder(selectedModelFolder, ideaProjectFiles); } catch (PropertyListParserException e) { e.printStackTrace(); throw new IOException("Failed to parse '.EntityModeler.plist'. " + StringUtils.getErrorMessage(e)); } if (!ideaProjectFiles.isEmpty()) { searchFolders = new LinkedHashSet<ManifestSearchFolder>(); for (File ideaProjectFile : ideaProjectFiles) { //System.out.println("IDEAProjectEOModelGroupFactory.getSearchFolders: Project = " + ideaProjectFile); Map<String, File> ideaLibraries = new HashMap<String, File>(); String ideaProjectPath = ideaProjectFile.getParentFile().getAbsolutePath(); Set<File> visitedModulePaths = new HashSet<File>(); try { XPathExpression ideaLibrariesExpression = XPathFactory.newInstance().newXPath().compile("project/component[@name='libraryTable']/library"); XPathExpression ideaModulesExpression = XPathFactory.newInstance().newXPath().compile("project/component[@name='ProjectModuleManager']/modules/module"); XPathExpression ideaClassesRootExpression = XPathFactory.newInstance().newXPath().compile("CLASSES/root"); Document ideaProjectDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(ideaProjectFile); NodeList ideaLibraryNodes = (NodeList) ideaLibrariesExpression.evaluate(ideaProjectDocument, XPathConstants.NODESET); for (int ideaLibraryNum = 0; ideaLibraryNum < ideaLibraryNodes.getLength(); ideaLibraryNum++) { Element ideaLibraryElement = (Element) ideaLibraryNodes.item(ideaLibraryNum); String libraryName = ideaLibraryElement.getAttribute("name"); NodeList rootNodes = (NodeList) ideaClassesRootExpression.evaluate(ideaLibraryElement, XPathConstants.NODESET); for (int rootNodeNum = 0; rootNodeNum < rootNodes.getLength(); rootNodeNum++) { Element rootNodeElement = (Element) rootNodes.item(rootNodeNum); String rootPath = rootNodeElement.getAttribute("url"); if (rootPath.contains(".framework/Resources")) { rootPath = rootPath.replaceAll("^[^:]+://", ""); rootPath = rootPath.replaceAll("\\$PROJECT_DIR\\$", ideaProjectPath); rootPath = rootPath.replaceAll("(.*\\.framework/Resources).*", "$1"); ideaLibraries.put(libraryName, new File(rootPath).getCanonicalFile()); //System.out.println("IDEAProjectEOModelGroupFactory.getSearchFolders: Library " + libraryName + "=" + ideaLibraries.get(libraryName)); break; } } } NodeList ideaModuleNodes = (NodeList) ideaModulesExpression.evaluate(ideaProjectDocument, XPathConstants.NODESET); for (int ideaModuleNum = 0; ideaModuleNum < ideaModuleNodes.getLength(); ideaModuleNum++) { Element ideaModuleElement = (Element) ideaModuleNodes.item(ideaModuleNum); String ideaModulePath = ideaModuleElement.getAttribute("filepath"); ideaModulePath = ideaModulePath.replaceAll("\\$PROJECT_DIR\\$", ideaProjectPath); File ideaModuleFile = new File(ideaModulePath).getCanonicalFile(); processIdeaModuleFile(ideaModuleFile, searchFolders, ideaLibraries, visitedModulePaths); } } catch (Exception e) { e.printStackTrace(); } } } //System.out.println("IDEAProjectEOModelGroupFactory.getSearchFolders: Search folders = " + searchFolders); return searchFolders == null ? null : new LinkedList<ManifestSearchFolder>(searchFolders); } protected void processIdeaModuleFile(File ideaModuleFile, Set<ManifestSearchFolder> searchFolders, Map<String, File> ideaLibraries, Set<File> visitedModulePaths) throws IOException, XPathExpressionException, SAXException, ParserConfigurationException { if (!ideaModuleFile.exists()) { return; } else if (visitedModulePaths.contains(ideaModuleFile)) { return; } visitedModulePaths.add(ideaModuleFile); //System.out.println("IDEAProjectEOModelGroupFactory.processIdeaModuleFile: Module file '" + ideaModuleFile + "' ..."); String ideaProjectPath = ideaModuleFile.getParentFile().getAbsolutePath(); Document ideaModuleDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(ideaModuleFile); XPathExpression sourceFoldersExpression = XPathFactory.newInstance().newXPath().compile("//module/component/content"); NodeList contentNodes = (NodeList) sourceFoldersExpression.evaluate(ideaModuleDocument, XPathConstants.NODESET); for (int contentNum = 0; contentNum < contentNodes.getLength(); contentNum++) { Element contentElement = (Element) contentNodes.item(contentNum); String contentPath = contentElement.getAttribute("url"); contentPath = contentPath.replaceAll("^file://", ""); contentPath = contentPath.replaceAll("\\$MODULE_DIR\\$", ideaProjectPath); File contentFolder = new File(contentPath).getCanonicalFile(); // System.out.println("IDEAProjectEOModelGroupFactory.processIdeaModuleFile: content folder = " + contentFolder); File resourcesFolder = new File(contentFolder, "Resources"); if (resourcesFolder.exists()) { searchFolders.add(new ManifestSearchFolder(resourcesFolder)); } else { // ... just only support project/Resources // searchFolders.add(new ManifestSearchFolder(contentFolder)); } } XPathExpression ideaModulesExpression = XPathFactory.newInstance().newXPath().compile("//module/component/orderEntry"); NodeList ideaModuleNodes = (NodeList) ideaModulesExpression.evaluate(ideaModuleDocument, XPathConstants.NODESET); for (int ideaModuleNum = 0; ideaModuleNum < ideaModuleNodes.getLength(); ideaModuleNum++) { Element ideaModuleElement = (Element) ideaModuleNodes.item(ideaModuleNum); String ideaModuleType = ideaModuleElement.getAttribute("type"); if ("module".equals(ideaModuleType)) { String ideaModuleName = ideaModuleElement.getAttribute("module-name"); File dependentModuleFile = new File(ideaModuleFile.getParentFile(), ideaModuleName + ".iml").getCanonicalFile(); processIdeaModuleFile(dependentModuleFile, searchFolders, ideaLibraries, visitedModulePaths); } else if ("library".equals(ideaModuleType)) { String ideaLibraryName = ideaModuleElement.getAttribute("name"); File ideaLibraryFolder = ideaLibraries.get(ideaLibraryName); if (ideaLibraryFolder != null) { // System.out.println("IDEAProjectEOModelGroupFactory.processIdeaModuleFile: library folder = " + ideaLibraryFolder); searchFolders.add(new ManifestSearchFolder(ideaLibraryFolder)); } } } } @SuppressWarnings("unchecked") public static void findIdeaProjectFilesInFolder(File folder, Set<File> ideaProjectFiles) throws IOException, PropertyListParserException { if (folder != null) { boolean foundProjectFiles = false; if (folder.isDirectory()) { //System.out.println("IDEAProjectEOModelGroupFactory.findIdeaProjectFilesInFolder: Looking in " + folder + " ..."); File projectLocator = new File(folder, ".EntityModeler.plist"); if (projectLocator.exists()) { //System.out.println("IDEAProjectEOModelGroupFactory.findIdeaProjectFilesInFolder: Found project locator '" + projectLocator + '.'); Map<String, Object> projectProperties = (Map<String, Object>) WOLPropertyListSerialization.propertyListWithContentsOfFile(projectLocator.getCanonicalPath(), new SimpleParserDataStructureFactory()); Map<String, List<String>> dependencies = (Map<String, List<String>>) projectProperties.get("Dependencies"); if (dependencies != null) { List<String> projectFilePaths = dependencies.get("IDEA"); if (projectFilePaths != null) { for (String projectFilePath : projectFilePaths) { File projectFile = new File(projectFilePath); if (!projectFile.exists()) { projectFile = new File(folder, projectFilePath); } if (projectFile.exists()) { projectFile = projectFile.getCanonicalFile(); if (IDEAProjectEOModelGroupFactory.isIdeaProjectFile(projectFile)) { //System.out.println("IDEAProjectEOModelGroupFactory.findIdeaProjectFilesInFolder: Found project '" + projectFile + "'."); ideaProjectFiles.add(projectFile.getCanonicalFile()); foundProjectFiles = true; } } } } } } else { File[] files = folder.listFiles(); if (files != null) { for (File file : files) { if (IDEAProjectEOModelGroupFactory.isIdeaProjectFile(file)) { //System.out.println("IDEAProjectEOModelGroupFactory.findIdeaProjectFilesInFolder: Found project '" + file + "'."); ideaProjectFiles.add(file.getCanonicalFile()); foundProjectFiles = true; } } } } } if (!foundProjectFiles) { File parentFolder = folder.getParentFile(); findIdeaProjectFilesInFolder(parentFolder, ideaProjectFiles); } } } public static boolean isIdeaProjectFile(File file) { return file.getName().endsWith(".ipr"); } }