KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > project > ant > AntBasedProjectFactorySingleton


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.project.ant;
21
22 import java.io.File JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.lang.ref.Reference JavaDoc;
25 import java.lang.ref.WeakReference JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.HashSet JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.Set JavaDoc;
32 import java.util.WeakHashMap JavaDoc;
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 JavaDoc;
47 import org.w3c.dom.Element JavaDoc;
48 import org.xml.sax.InputSource JavaDoc;
49 import org.xml.sax.SAXException JavaDoc;
50
51 /**
52  * Singleton {@link ProjectFactory} implementation which handles all Ant-based
53  * projects by delegating some functionality to registered Ant project types.
54  * @author Jesse Glick
55  */

56 public final class AntBasedProjectFactorySingleton implements ProjectFactory {
57     
58     public static final String JavaDoc PROJECT_XML_PATH = "nbproject/project.xml"; // NOI18N
59

60     public static final String JavaDoc PROJECT_NS = "http://www.netbeans.org/ns/project/1"; // NOI18N
61

62     /** Construct the singleton. */
63     public AntBasedProjectFactorySingleton() {}
64     
65     private static final Map JavaDoc<Project,Reference JavaDoc<AntProjectHelper>> project2Helper = new WeakHashMap JavaDoc<Project,Reference JavaDoc<AntProjectHelper>>();
66     private static final Map JavaDoc<AntProjectHelper,Reference JavaDoc<Project>> helper2Project = new WeakHashMap JavaDoc<AntProjectHelper,Reference JavaDoc<Project>>();
67     private static final Map JavaDoc<AntBasedProjectType,List JavaDoc<Reference JavaDoc<AntProjectHelper>>> type2Projects = new HashMap JavaDoc<AntBasedProjectType,List JavaDoc<Reference JavaDoc<AntProjectHelper>>>(); //for second part of #42738
68
private static final Lookup.Result<AntBasedProjectType> antBasedProjectTypes;
69     private static Map JavaDoc<String JavaDoc,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 JavaDoc<AntBasedProjectType> oldTypes = type2Projects.keySet();
76                     Set JavaDoc<AntBasedProjectType> removed = new HashSet JavaDoc<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 JavaDoc<AntBasedProjectType> removed) {
89         for (AntBasedProjectType type : removed) {
90             List JavaDoc<Reference JavaDoc<AntProjectHelper>> projects = type2Projects.get(type);
91             if (projects != null) {
92                 for (Reference JavaDoc<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 JavaDoc type) {
104         if (antBasedProjectTypesByType == null) {
105             antBasedProjectTypesByType = new HashMap JavaDoc<String JavaDoc,AntBasedProjectType>();
106             // No need to synchronize similar calls since this is called only inside
107
// ProjectManager.mutex. However dkonecny says that allInstances can
108
// trigger a LookupEvent which would clear antBasedProjectTypesByType,
109
// so need to initialize that later; and who knows then Lookup changes
110
// might be fired.
111
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 JavaDoc dirF = FileUtil.toFile(dir);
120         if (dirF == null) {
121             return false;
122         }
123         // Just check whether project.xml exists. Do not attempt to parse it, etc.
124
// Do not use FileObject.getFileObject since that may load other sister files.
125
File JavaDoc projectXmlF = new File JavaDoc(new File JavaDoc(dirF, "nbproject"), "project.xml"); // NOI18N
126
return projectXmlF.isFile();
127     }
128     
129     public Project loadProject(FileObject projectDirectory, ProjectState state) throws IOException JavaDoc {
130         if (FileUtil.toFile(projectDirectory) == null) {
131             return null;
132         }
133         FileObject projectFile = projectDirectory.getFileObject(PROJECT_XML_PATH);
134         //#54488: Added check for virtual
135
if (projectFile == null || !projectFile.isData() || projectFile.isVirtual()) {
136             return null;
137         }
138         File JavaDoc projectDiskFile = FileUtil.toFile(projectFile);
139         //#63834: if projectFile exists and projectDiskFile does not, do nothing:
140
if (projectDiskFile == null) {
141             return null;
142         }
143         Document JavaDoc projectXml;
144         try {
145             projectXml = XMLUtil.parse(new InputSource JavaDoc(projectDiskFile.toURI().toString()), false, true, Util.defaultErrorHandler(), null);
146         } catch (SAXException JavaDoc e) {
147             IOException JavaDoc ioe = (IOException JavaDoc) new IOException JavaDoc(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 JavaDoc projectEl = projectXml.getDocumentElement();
154         if (!"project".equals(projectEl.getLocalName()) || !PROJECT_NS.equals(projectEl.getNamespaceURI())) { // NOI18N
155
return null;
156         }
157         Element JavaDoc typeEl = Util.findElement(projectEl, "type", PROJECT_NS); // NOI18N
158
if (typeEl == null) {
159             return null;
160         }
161         String JavaDoc 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 JavaDoc<AntProjectHelper>(helper));
172         helper2Project.put(helper, new WeakReference JavaDoc<Project>(project));
173         List JavaDoc<Reference JavaDoc<AntProjectHelper>> l = type2Projects.get(provider);
174         
175         if (l == null) {
176             type2Projects.put(provider, l = new ArrayList JavaDoc<Reference JavaDoc<AntProjectHelper>>());
177         }
178         
179         l.add(new WeakReference JavaDoc<AntProjectHelper>(helper));
180         
181         return project;
182     }
183     
184     public void saveProject(Project project) throws IOException JavaDoc, ClassCastException JavaDoc {
185         Reference JavaDoc<AntProjectHelper> helperRef = project2Helper.get(project);
186         if (helperRef == null) {
187             throw new ClassCastException JavaDoc(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     /**
195      * Get the project corresponding to a helper.
196      * For use from {@link AntProjectHelper}.
197      * @param helper an Ant project helper object
198      * @return the corresponding project
199      */

200     public static Project getProjectFor(AntProjectHelper helper) {
201         Reference JavaDoc<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     /**
209      * Get the helper corresponding to a project.
210      * For use from {@link ProjectGenerator}.
211      * @param project an Ant-based project
212      * @return the corresponding Ant project helper object, or null if it is unknown
213      */

214     public static AntProjectHelper getHelperFor(Project p) {
215         Reference JavaDoc<AntProjectHelper> helperRef = project2Helper.get(p);
216         return helperRef != null ? helperRef.get() : null;
217     }
218     
219     /**
220      * Callback to create and access AntProjectHelper objects from outside its package.
221      */

222     public interface AntProjectHelperCallback {
223         AntProjectHelper createHelper(FileObject dir, Document JavaDoc projectXml, ProjectState state, AntBasedProjectType type);
224         void save(AntProjectHelper helper) throws IOException JavaDoc;
225     }
226     /** Defined in AntProjectHelper's static initializer. */
227     public static AntProjectHelperCallback HELPER_CALLBACK;
228     static {
229         Class JavaDoc<?> c = AntProjectHelper.class;
230         try {
231             Class.forName(c.getName(), true, c.getClassLoader());
232         } catch (ClassNotFoundException JavaDoc e) {
233             assert false : e;
234         }
235         assert HELPER_CALLBACK != null;
236     }
237     
238 }
239
Popular Tags