1 19 20 package org.netbeans.modules.project.ant; 21 22 import java.io.File ; 23 import java.io.IOException ; 24 import java.lang.ref.Reference ; 25 import java.lang.ref.WeakReference ; 26 import java.util.ArrayList ; 27 import java.util.HashMap ; 28 import java.util.HashSet ; 29 import java.util.List ; 30 import java.util.Map ; 31 import java.util.Set ; 32 import java.util.WeakHashMap ; 33 import org.netbeans.api.project.Project; 34 import org.netbeans.spi.project.ProjectFactory; 35 import org.netbeans.spi.project.ProjectState; 36 import org.netbeans.spi.project.support.ant.AntBasedProjectType; 37 import org.netbeans.spi.project.support.ant.AntProjectHelper; 38 import org.openide.filesystems.FileObject; 39 import org.openide.filesystems.FileUtil; 40 import org.openide.util.Exceptions; 41 import org.openide.util.Lookup; 42 import org.openide.util.LookupEvent; 43 import org.openide.util.LookupListener; 44 import org.openide.util.NbBundle; 45 import org.openide.xml.XMLUtil; 46 import org.w3c.dom.Document ; 47 import org.w3c.dom.Element ; 48 import org.xml.sax.InputSource ; 49 import org.xml.sax.SAXException ; 50 51 56 public final class AntBasedProjectFactorySingleton implements ProjectFactory { 57 58 public static final String PROJECT_XML_PATH = "nbproject/project.xml"; 60 public static final String PROJECT_NS = "http://www.netbeans.org/ns/project/1"; 62 63 public AntBasedProjectFactorySingleton() {} 64 65 private static final Map <Project,Reference <AntProjectHelper>> project2Helper = new WeakHashMap <Project,Reference <AntProjectHelper>>(); 66 private static final Map <AntProjectHelper,Reference <Project>> helper2Project = new WeakHashMap <AntProjectHelper,Reference <Project>>(); 67 private static final Map <AntBasedProjectType,List <Reference <AntProjectHelper>>> type2Projects = new HashMap <AntBasedProjectType,List <Reference <AntProjectHelper>>>(); private static final Lookup.Result<AntBasedProjectType> antBasedProjectTypes; 69 private static Map <String ,AntBasedProjectType> antBasedProjectTypesByType = null; 70 static { 71 antBasedProjectTypes = Lookup.getDefault().lookupResult(AntBasedProjectType.class); 72 antBasedProjectTypes.addLookupListener(new LookupListener() { 73 public void resultChanged(LookupEvent ev) { 74 synchronized (AntBasedProjectFactorySingleton.class) { 75 Set <AntBasedProjectType> oldTypes = type2Projects.keySet(); 76 Set <AntBasedProjectType> removed = new HashSet <AntBasedProjectType>(oldTypes); 77 78 removed.removeAll(antBasedProjectTypes.allInstances()); 79 80 antBasedProjectTypesRemoved(removed); 81 82 antBasedProjectTypesByType = null; 83 } 84 } 85 }); 86 } 87 88 private static void antBasedProjectTypesRemoved(Set <AntBasedProjectType> removed) { 89 for (AntBasedProjectType type : removed) { 90 List <Reference <AntProjectHelper>> projects = type2Projects.get(type); 91 if (projects != null) { 92 for (Reference <AntProjectHelper> r : projects) { 93 AntProjectHelper helper = r.get(); 94 if (helper != null) { 95 helper.notifyDeleted(); 96 } 97 } 98 } 99 type2Projects.remove(type); 100 } 101 } 102 103 private static synchronized AntBasedProjectType findAntBasedProjectType(String type) { 104 if (antBasedProjectTypesByType == null) { 105 antBasedProjectTypesByType = new HashMap <String ,AntBasedProjectType>(); 106 for (AntBasedProjectType abpt : antBasedProjectTypes.allInstances()) { 112 antBasedProjectTypesByType.put(abpt.getType(), abpt); 113 } 114 } 115 return antBasedProjectTypesByType.get(type); 116 } 117 118 public boolean isProject(FileObject dir) { 119 File dirF = FileUtil.toFile(dir); 120 if (dirF == null) { 121 return false; 122 } 123 File projectXmlF = new File (new File (dirF, "nbproject"), "project.xml"); return projectXmlF.isFile(); 127 } 128 129 public Project loadProject(FileObject projectDirectory, ProjectState state) throws IOException { 130 if (FileUtil.toFile(projectDirectory) == null) { 131 return null; 132 } 133 FileObject projectFile = projectDirectory.getFileObject(PROJECT_XML_PATH); 134 if (projectFile == null || !projectFile.isData() || projectFile.isVirtual()) { 136 return null; 137 } 138 File projectDiskFile = FileUtil.toFile(projectFile); 139 if (projectDiskFile == null) { 141 return null; 142 } 143 Document projectXml; 144 try { 145 projectXml = XMLUtil.parse(new InputSource (projectDiskFile.toURI().toString()), false, true, Util.defaultErrorHandler(), null); 146 } catch (SAXException e) { 147 IOException ioe = (IOException ) new IOException (projectDiskFile + ": " + e.toString()).initCause(e); 148 Exceptions.attachLocalizedMessage(ioe, NbBundle.getMessage(AntBasedProjectFactorySingleton.class, 149 "AntBasedProjectFactorySingleton.parseError", 150 projectDiskFile.getAbsolutePath(), e.getMessage())); 151 throw ioe; 152 } 153 Element projectEl = projectXml.getDocumentElement(); 154 if (!"project".equals(projectEl.getLocalName()) || !PROJECT_NS.equals(projectEl.getNamespaceURI())) { return null; 156 } 157 Element typeEl = Util.findElement(projectEl, "type", PROJECT_NS); if (typeEl == null) { 159 return null; 160 } 161 String type = Util.findText(typeEl); 162 if (type == null) { 163 return null; 164 } 165 AntBasedProjectType provider = findAntBasedProjectType(type); 166 if (provider == null) { 167 return null; 168 } 169 AntProjectHelper helper = HELPER_CALLBACK.createHelper(projectDirectory, projectXml, state, provider); 170 Project project = provider.createProject(helper); 171 project2Helper.put(project, new WeakReference <AntProjectHelper>(helper)); 172 helper2Project.put(helper, new WeakReference <Project>(project)); 173 List <Reference <AntProjectHelper>> l = type2Projects.get(provider); 174 175 if (l == null) { 176 type2Projects.put(provider, l = new ArrayList <Reference <AntProjectHelper>>()); 177 } 178 179 l.add(new WeakReference <AntProjectHelper>(helper)); 180 181 return project; 182 } 183 184 public void saveProject(Project project) throws IOException , ClassCastException { 185 Reference <AntProjectHelper> helperRef = project2Helper.get(project); 186 if (helperRef == null) { 187 throw new ClassCastException (project.getClass().getName()); 188 } 189 AntProjectHelper helper = helperRef.get(); 190 assert helper != null : "AntProjectHelper collected for " + project; 191 HELPER_CALLBACK.save(helper); 192 } 193 194 200 public static Project getProjectFor(AntProjectHelper helper) { 201 Reference <Project> projectRef = helper2Project.get(helper); 202 assert projectRef != null : "Found a Project reference for " + helper; 203 Project p = projectRef.get(); 204 assert p != null : "Found a non-null Project for " + helper; 205 return p; 206 } 207 208 214 public static AntProjectHelper getHelperFor(Project p) { 215 Reference <AntProjectHelper> helperRef = project2Helper.get(p); 216 return helperRef != null ? helperRef.get() : null; 217 } 218 219 222 public interface AntProjectHelperCallback { 223 AntProjectHelper createHelper(FileObject dir, Document projectXml, ProjectState state, AntBasedProjectType type); 224 void save(AntProjectHelper helper) throws IOException ; 225 } 226 227 public static AntProjectHelperCallback HELPER_CALLBACK; 228 static { 229 Class <?> c = AntProjectHelper.class; 230 try { 231 Class.forName(c.getName(), true, c.getClassLoader()); 232 } catch (ClassNotFoundException e) { 233 assert false : e; 234 } 235 assert HELPER_CALLBACK != null; 236 } 237 238 } 239 | Popular Tags |