KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > apt > core > internal > util > FactoryPathUtil


1 /*******************************************************************************
2  * Copyright (c) 2005, 2007 BEA Systems, Inc.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * jgarms@bea.com - initial API and implementation
10  *
11  *******************************************************************************/

12 package org.eclipse.jdt.apt.core.internal.util;
13
14 import java.io.File JavaDoc;
15 import java.io.IOException JavaDoc;
16 import java.io.StringReader JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.LinkedHashMap JavaDoc;
19 import java.util.Map JavaDoc;
20
21 import javax.xml.parsers.DocumentBuilder JavaDoc;
22 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
23 import javax.xml.parsers.ParserConfigurationException JavaDoc;
24
25 import org.eclipse.core.resources.IFile;
26 import org.eclipse.core.resources.IProject;
27 import org.eclipse.core.resources.IResource;
28 import org.eclipse.core.runtime.CoreException;
29 import org.eclipse.core.runtime.IPath;
30 import org.eclipse.core.runtime.IStatus;
31 import org.eclipse.core.runtime.Path;
32 import org.eclipse.core.runtime.Status;
33 import org.eclipse.jdt.apt.core.internal.AptPlugin;
34 import org.eclipse.jdt.apt.core.internal.ExtJarFactoryContainer;
35 import org.eclipse.jdt.apt.core.internal.FactoryPluginManager;
36 import org.eclipse.jdt.apt.core.internal.VarJarFactoryContainer;
37 import org.eclipse.jdt.apt.core.internal.WkspJarFactoryContainer;
38 import org.eclipse.jdt.apt.core.internal.util.FactoryContainer.FactoryType;
39 import org.eclipse.jdt.apt.core.util.IFactoryPath;
40 import org.eclipse.jdt.core.IJavaProject;
41 import org.w3c.dom.Element JavaDoc;
42 import org.w3c.dom.Node JavaDoc;
43 import org.w3c.dom.NodeList JavaDoc;
44 import org.xml.sax.InputSource JavaDoc;
45 import org.xml.sax.SAXException JavaDoc;
46
47 /**
48  * Utility class for dealing with the factory path
49  */

50 public final class FactoryPathUtil {
51     
52     private static final String JavaDoc FACTORYPATH_TAG = "factorypath"; //$NON-NLS-1$
53
private static final String JavaDoc FACTORYPATH_ENTRY_TAG = "factorypathentry"; //$NON-NLS-1$
54
private static final String JavaDoc KIND = "kind"; //$NON-NLS-1$
55
private static final String JavaDoc ID = "id"; //$NON-NLS-1$
56
private static final String JavaDoc ENABLED = "enabled"; //$NON-NLS-1$
57
private static final String JavaDoc RUN_IN_BATCH_MODE = "runInBatchMode"; //$NON-NLS-1$
58

59     private static final String JavaDoc FACTORYPATH_FILE = ".factorypath"; //$NON-NLS-1$
60

61     // four spaces for indent
62
private static final String JavaDoc INDENT = " "; //$NON-NLS-1$
63

64     // Private c-tor to prevent construction
65
private FactoryPathUtil() {}
66     
67     /**
68      * Test whether a resource is a factory path file. The criteria are
69      * that it is a file, it belongs to a project, it is located in the root
70      * of that project, and it is named ".factorypath". Note that the
71      * workspace-wide factorypath file does NOT meet these criteria.
72      * @param res any sort of IResource, or null.
73      * @return true if the resource is a project-specific factory path file.
74      */

75     public static boolean isFactoryPathFile(IResource res) {
76         if (res == null || res.getType() != IResource.FILE || res.getProject() == null) {
77             return false;
78         }
79         IPath path = res.getProjectRelativePath();
80         if (path.segmentCount() != 1) {
81             return false;
82         }
83         return FACTORYPATH_FILE.equals(path.lastSegment());
84     }
85     
86     /**
87      * Loads a map of factory containers from the factory path for a given
88      * project. If no factorypath file was found, returns null.
89      */

90     public static Map JavaDoc<FactoryContainer, FactoryPath.Attributes> readFactoryPathFile(IJavaProject jproj)
91         throws CoreException
92     {
93         String JavaDoc data = null;
94         try {
95             // If project is null, use workspace-level data
96
if (jproj == null) {
97                 File JavaDoc file = getFileForWorkspace();
98                 if (!file.exists()) {
99                     return null;
100                 }
101                 data = FileSystemUtil.getContentsOfFile(file);
102             }
103             else {
104                 IFile ifile = getIFileForProject(jproj);
105                 if (!ifile.exists()) {
106                     return null;
107                 }
108                 data = FileSystemUtil.getContentsOfIFile(ifile);
109             }
110         }
111         catch (IOException JavaDoc e) {
112             throw new CoreException(new Status(IStatus.ERROR, AptPlugin.PLUGIN_ID, -1, Messages.FactoryPathUtil_status_ioException, e));
113         }
114         
115         return FactoryPathUtil.decodeFactoryPath(data);
116     }
117     
118     /**
119      * Stores a map of factory containers to the factorypath file
120      * for a given project. If null is passed in, the factorypath file
121      * is deleted.
122      */

123     public static void saveFactoryPathFile(IJavaProject jproj, Map JavaDoc<FactoryContainer, FactoryPath.Attributes> containers)
124         throws CoreException
125     {
126         IFile projFile;
127         File JavaDoc wkspFile;
128         if (jproj != null) {
129             projFile = getIFileForProject(jproj);
130             wkspFile = null;
131         }
132         else {
133             wkspFile = getFileForWorkspace();
134             projFile = null;
135         }
136         
137         try {
138             if (containers != null) {
139                 String JavaDoc data = FactoryPathUtil.encodeFactoryPath(containers);
140                 // If project is null, set workspace-level data
141
if (jproj == null) {
142                     FileSystemUtil.writeStringToFile(wkspFile, data);
143                 }
144                 else {
145                     FileSystemUtil.writeStringToIFile(projFile, data);
146                 }
147             }
148             else { // restore defaults by deleting the factorypath file.
149
if (jproj != null) {
150                     projFile.delete(true, null);
151                 }
152                 else {
153                     wkspFile.delete();
154                 }
155             }
156         }
157         catch (IOException JavaDoc e) {
158             throw new CoreException(new Status(IStatus.ERROR, AptPlugin.PLUGIN_ID, -1, Messages.FactoryPathUtil_status_ioException, e));
159         }
160     }
161     
162     /**
163      * Returns an XML string encoding all of the factories.
164      * @param factories
165      */

166     public static String JavaDoc encodeFactoryPath(Map JavaDoc<FactoryContainer, FactoryPath.Attributes> factories) {
167         StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
168         sb.append("<").append(FACTORYPATH_TAG).append(">\n"); //$NON-NLS-1$ //$NON-NLS-2$
169
for (Map.Entry JavaDoc<FactoryContainer, FactoryPath.Attributes> entry : factories.entrySet()) {
170             FactoryContainer container = entry.getKey();
171             FactoryPath.Attributes attr = entry.getValue();
172             sb.append(INDENT);
173             sb.append("<"); //$NON-NLS-1$
174
sb.append(FACTORYPATH_ENTRY_TAG).append(" "); //$NON-NLS-1$
175
sb.append(KIND).append("=\"").append(container.getType()).append("\" "); //$NON-NLS-1$ //$NON-NLS-2$
176
sb.append(ID).append("=\"").append(container.getId()).append("\" "); //$NON-NLS-1$ //$NON-NLS-2$
177
sb.append(ENABLED).append("=\"").append(attr.isEnabled()).append("\" "); //$NON-NLS-1$ //$NON-NLS-2$
178
sb.append(RUN_IN_BATCH_MODE).append("=\"").append(attr.runInBatchMode()).append("\"/>\n"); //$NON-NLS-1$ //$NON-NLS-2$
179
}
180         sb.append("</").append(FACTORYPATH_TAG).append(">\n"); //$NON-NLS-1$ //$NON-NLS-2$
181

182         return sb.toString();
183     }
184     
185     /**
186      * Create a factory container based on an external jar file (not in the
187      * workspace).
188      * @param jar a java.io.File representing the jar file.
189      */

190     public static FactoryContainer newExtJarFactoryContainer(File JavaDoc jar) {
191         return new ExtJarFactoryContainer(jar);
192     }
193     
194     /**
195      * Create a factory container based on a jar file in the workspace.
196      * @param jar an Eclipse IPath representing the jar file; the path is
197      * relative to the workspace root.
198      */

199     public static FactoryContainer newWkspJarFactoryContainer(IPath jar) {
200         return new WkspJarFactoryContainer(jar);
201     }
202     
203     /**
204      * Create a factory container based on an external jar file specified
205      * by a classpath variable (and possibly a path relative to that variable).
206      * @param jar an Eclipse IPath representing the jar file; the first
207      * segment of the path is assumed to be the variable name.
208      */

209     public static FactoryContainer newVarJarFactoryContainer(IPath jar) {
210         return new VarJarFactoryContainer(jar);
211     }
212
213     public static Map JavaDoc<FactoryContainer, FactoryPath.Attributes> decodeFactoryPath(final String JavaDoc xmlFactoryPath)
214     throws CoreException
215     {
216         Map JavaDoc<FactoryContainer, FactoryPath.Attributes> result = new LinkedHashMap JavaDoc<FactoryContainer, FactoryPath.Attributes>();
217         StringReader JavaDoc reader = new StringReader JavaDoc(xmlFactoryPath);
218         Element JavaDoc fpElement = null;
219
220         try {
221             DocumentBuilder JavaDoc parser =
222                 DocumentBuilderFactory.newInstance().newDocumentBuilder();
223             fpElement = parser.parse(new InputSource JavaDoc(reader)).getDocumentElement();
224
225         }
226         catch (IOException JavaDoc e) {
227             throw new CoreException(new Status(IStatus.ERROR, AptPlugin.PLUGIN_ID, -1, Messages.FactoryPathUtil_status_ioException, e));
228         }
229         catch (SAXException JavaDoc e) {
230             throw new CoreException(new Status(IStatus.ERROR, AptPlugin.PLUGIN_ID, -1, Messages.FactoryPathUtil_status_couldNotParse, e));
231         }
232         catch (ParserConfigurationException JavaDoc e) {
233             throw new CoreException(new Status(IStatus.ERROR, AptPlugin.PLUGIN_ID, -1, Messages.FactoryPathUtil_status_parserConfigError, e));
234         }
235         finally {
236             reader.close();
237         }
238
239         if (!fpElement.getNodeName().equalsIgnoreCase(FACTORYPATH_TAG)) {
240             IOException JavaDoc e = new IOException JavaDoc("Incorrect file format. File must begin with " + FACTORYPATH_TAG); //$NON-NLS-1$
241
throw new CoreException(new Status(IStatus.ERROR, AptPlugin.PLUGIN_ID, -1, Messages.FactoryPathUtil_status_ioException, e));
242         }
243         NodeList JavaDoc nodes = fpElement.getElementsByTagName(FACTORYPATH_ENTRY_TAG);
244         for (int i=0; i < nodes.getLength(); i++) {
245             Node JavaDoc node = nodes.item(i);
246             if (node.getNodeType() == Node.ELEMENT_NODE) {
247                 Element JavaDoc element = (Element JavaDoc)node;
248                 String JavaDoc kindString = element.getAttribute(KIND);
249                 // deprecated container type "JAR" is now "EXTJAR"
250
if ("JAR".equals(kindString)) { //$NON-NLS-1$
251
kindString = "EXTJAR"; //$NON-NLS-1$
252
}
253                 String JavaDoc idString = element.getAttribute(ID);
254                 String JavaDoc enabledString = element.getAttribute(ENABLED);
255                 String JavaDoc runInAptModeString = element.getAttribute(RUN_IN_BATCH_MODE);
256                 FactoryType kind = FactoryType.valueOf(kindString);
257                 FactoryContainer container = null;
258                 switch (kind) {
259
260                 case WKSPJAR :
261                     container = newWkspJarFactoryContainer(new Path(idString));
262                     break;
263
264                 case EXTJAR :
265                     container = newExtJarFactoryContainer(new File JavaDoc(idString));
266                     break;
267
268                 case VARJAR :
269                     container = newVarJarFactoryContainer(new Path(idString));
270                     break;
271
272                 case PLUGIN :
273                     container = FactoryPluginManager.getPluginFactoryContainer(idString);
274                     break;
275
276                 default :
277                     throw new IllegalStateException JavaDoc("Unrecognized kind: " + kind + ". Original string: " + kindString); //$NON-NLS-1$ //$NON-NLS-2$
278
}
279
280                 if (null != container) {
281                     FactoryPath.Attributes a = new FactoryPath.Attributes(
282                             Boolean.parseBoolean(enabledString), Boolean.parseBoolean(runInAptModeString));
283                     result.put(container, a);
284                 }
285             }
286         }
287
288         return result;
289     }
290     
291     /**
292      * Get a file designator for the workspace-level factory path settings file.
293      * Typically this is [workspace]/.metadata/plugins/org.eclipse.jdt.apt.core/.factorypath
294      * @return a java.io.File
295      */

296     private static File JavaDoc getFileForWorkspace() {
297         return AptPlugin.getPlugin().getStateLocation().append(FACTORYPATH_FILE).toFile();
298     }
299
300     /**
301      * Get an Eclipse IFile for the project-level factory path settings file.
302      * Typically this is [project]/.factorypath
303      * @param jproj must not be null
304      * @return an Eclipse IFile
305      */

306     private static IFile getIFileForProject(IJavaProject jproj) {
307         IProject proj = jproj.getProject();
308         return proj.getFile(FACTORYPATH_FILE);
309     }
310
311     /**
312      * Does a factory path file already exist for the specified project,
313      * or for the workspace as a whole?
314      * @param jproj if this is null, check for workspace-level settings.
315      * @return true if a settings file exists.
316      */

317     public static boolean doesFactoryPathFileExist(IJavaProject jproj) {
318         if (jproj == null) {
319             File JavaDoc wkspFile = getFileForWorkspace();
320             return wkspFile.exists();
321         }
322         else {
323             IFile projFile = getIFileForProject(jproj);
324             return projFile.exists();
325         }
326     }
327
328     /**
329      * Calculates the active factory path for the specified project. This
330      * depends on the stored information in the .factorypath file, as well as
331      * on the set of plugins that were found at load time of this Eclipse instance.
332      * Returns all containers for the provided project, including disabled ones.
333      * @param jproj The java project in question, or null for the workspace
334      * @return an ordered map, where the key is the container and the value
335      * indicates whether the container is enabled.
336      */

337     private static synchronized Map JavaDoc<FactoryContainer, FactoryPath.Attributes> calculatePath(IJavaProject jproj) {
338         Map JavaDoc<FactoryContainer, FactoryPath.Attributes> map = null;
339         boolean foundPerProjFile = false;
340         if (jproj != null) {
341             try {
342                 map = FactoryPathUtil.readFactoryPathFile(jproj);
343                 foundPerProjFile = (map != null);
344             }
345             catch (CoreException ce) {
346                 AptPlugin.log(ce, "Could not get factory containers for project: " + jproj); //$NON-NLS-1$
347
}
348         }
349         // Workspace if no project data was found
350
if (map == null) {
351             try {
352                 map = FactoryPathUtil.readFactoryPathFile(null);
353             }
354             catch (CoreException ce) {
355                 AptPlugin.log(ce, "Could not get factory containers for project: " + jproj); //$NON-NLS-1$
356
}
357         }
358         // if no project and no workspace data was found, we'll get the defaults
359
if (map == null) {
360             map = new LinkedHashMap JavaDoc<FactoryContainer, FactoryPath.Attributes>();
361         }
362         boolean disableNewPlugins = (jproj != null) && foundPerProjFile;
363         updatePluginContainers(map, disableNewPlugins);
364         return map;
365     }
366     
367     /**
368      * Removes missing plugin containers, and adds any plugin containers
369      * that were added since the map was originally created. The order
370      * of the original list will be maintained, and new entries will be
371      * added to the end of the list in alphabetic order. The resulting
372      * list has the same contents as PLUGIN_FACTORY_MAP (that is, all the
373      * loaded plugins and nothing else), but the order is as close as possible
374      * to the input.
375      *
376      * @param path the factory path (in raw Map form) to be modified.
377      * @param disableNewPlugins if true, newly discovered plugins will be
378      * disabled. If false, they will be enabled or disabled according to
379      * their setting in the extension declaration.
380      */

381     private static void updatePluginContainers(
382             Map JavaDoc<FactoryContainer, FactoryPath.Attributes> path, boolean disableNewPlugins) {
383         
384         // Get the alphabetically-ordered list of all plugins we found at startup.
385
Map JavaDoc<FactoryContainer, FactoryPath.Attributes> pluginContainers = FactoryPluginManager.getAllPluginFactoryContainers();
386         
387         // Remove from the path any plugins which we did not find at startup
388
for (Iterator JavaDoc<FactoryContainer> i = path.keySet().iterator(); i.hasNext(); ) {
389             FactoryContainer fc = i.next();
390             if (fc.getType() == FactoryContainer.FactoryType.PLUGIN && !pluginContainers.containsKey(fc)) {
391                 i.remove();
392             }
393         }
394         
395         // Add to the end any plugins which are not in the path (i.e., which
396
// have been discovered since the config was last saved)
397
for (Map.Entry JavaDoc<FactoryContainer, FactoryPath.Attributes> entry : pluginContainers.entrySet()) {
398             if (!path.containsKey(entry.getKey())) {
399                 FactoryPath.Attributes newAttr;
400                 FactoryPath.Attributes oldAttr = entry.getValue();
401                 if (disableNewPlugins) {
402                     newAttr = new FactoryPath.Attributes(false, oldAttr.runInBatchMode());
403                 } else {
404                     newAttr = oldAttr;
405                 }
406                 path.put(entry.getKey(), newAttr);
407             }
408         }
409     }
410
411     /**
412      * Get a factory path corresponding to the default values: if jproj is
413      * non-null, return the current workspace factory path (workspace prefs
414      * are the default for a project); if jproj is null, return the default
415      * list of plugin factories (which is the "factory default").
416      */

417     public static IFactoryPath getDefaultFactoryPath(IJavaProject jproj) {
418         FactoryPath fp = new FactoryPath();
419         if (jproj != null) {
420             fp.setContainers(calculatePath(null));
421         }
422         else {
423             fp.setContainers(FactoryPluginManager.getAllPluginFactoryContainers());
424         }
425         return fp;
426     }
427
428     public static FactoryPath getFactoryPath(IJavaProject jproj) {
429         Map JavaDoc<FactoryContainer, FactoryPath.Attributes> map = calculatePath(jproj);
430         FactoryPath fp = new FactoryPath();
431         fp.setContainers(map);
432         return fp;
433     }
434
435     public static void setFactoryPath(IJavaProject jproj, FactoryPath path)
436             throws CoreException {
437         Map JavaDoc<FactoryContainer, FactoryPath.Attributes> map = (path != null) ?
438                 path.getAllContainers() : null;
439         saveFactoryPathFile(jproj, map);
440     }
441     
442
443 }
444
Popular Tags