KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > launching > VMDefinitionsContainer


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
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  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.launching;
12
13
14 import java.io.BufferedInputStream JavaDoc;
15 import java.io.File JavaDoc;
16 import java.io.IOException JavaDoc;
17 import java.io.InputStream JavaDoc;
18 import java.net.MalformedURLException JavaDoc;
19 import java.net.URL JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.Set JavaDoc;
26
27 import javax.xml.parsers.DocumentBuilder JavaDoc;
28 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
29 import javax.xml.parsers.ParserConfigurationException JavaDoc;
30 import javax.xml.transform.TransformerException JavaDoc;
31
32 import org.eclipse.core.runtime.IPath;
33 import org.eclipse.core.runtime.Path;
34 import org.eclipse.jdt.launching.IVMInstall;
35 import org.eclipse.jdt.launching.IVMInstall2;
36 import org.eclipse.jdt.launching.IVMInstallType;
37 import org.eclipse.jdt.launching.JavaRuntime;
38 import org.eclipse.jdt.launching.LibraryLocation;
39 import org.eclipse.jdt.launching.VMStandin;
40 import org.w3c.dom.Document JavaDoc;
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 import org.xml.sax.helpers.DefaultHandler JavaDoc;
47
48 /**
49  * This is a container for VM definitions such as the VM definitions that are
50  * stored in the workbench preferences.
51  * <p>
52  * An instance of this class may be obtained from an XML document by calling
53  * <code>parseXMLIntoContainer</code>.
54  * </p>
55  * <p>
56  * An instance of this class may be translated into an XML document by calling
57  * <code>getAsXML</code>.
58  * </p>
59  * <p>
60  * Clients may instantiate this class; it is not intended to be subclassed.
61  * </p>
62  *
63  * @since 2.1
64  */

65 public class VMDefinitionsContainer {
66         
67     /**
68      * Map of VMInstallTypes to Lists of corresponding VMInstalls.
69      */

70     private Map JavaDoc fVMTypeToVMMap;
71     
72     /**
73      * Cached list of VMs in this container
74      */

75     private List JavaDoc fVMList;
76     
77     /**
78      * VMs managed by this container whose install locations don't actually exist.
79      */

80     private List JavaDoc fInvalidVMList;
81             
82     /**
83      * The composite identifier of the default VM. This consists of the install type ID
84      * plus an ID for the VM.
85      */

86     private String JavaDoc fDefaultVMInstallCompositeID;
87     
88     /**
89      * The identifier of the connector to use for the default VM.
90      */

91     private String JavaDoc fDefaultVMInstallConnectorTypeID;
92     
93     /**
94      * Constructs an empty VM container
95      */

96     public VMDefinitionsContainer() {
97         fVMTypeToVMMap = new HashMap JavaDoc(10);
98         fInvalidVMList = new ArrayList JavaDoc(10);
99         fVMList = new ArrayList JavaDoc(10);
100     }
101         
102     /**
103      * Add the specified VM to the VM definitions managed by this container.
104      * <p>
105      * If distinguishing valid from invalid VMs is important, the specified VM must
106      * have already had its install location set. An invalid VM is one whose install
107      * location doesn't exist.
108      * </p>
109      *
110      * @param vm the VM to be added to this container
111      */

112     public void addVM(IVMInstall vm) {
113         if (!fVMList.contains(vm)) {
114             IVMInstallType vmInstallType = vm.getVMInstallType();
115             List JavaDoc vmList = (List JavaDoc) fVMTypeToVMMap.get(vmInstallType);
116             if (vmList == null) {
117                 vmList = new ArrayList JavaDoc(3);
118                 fVMTypeToVMMap.put(vmInstallType, vmList);
119             }
120             vmList.add(vm);
121             File JavaDoc installLocation = vm.getInstallLocation();
122             if (installLocation == null || !vmInstallType.validateInstallLocation(installLocation).isOK()) {
123                 fInvalidVMList.add(vm);
124             }
125             fVMList.add(vm);
126         }
127     }
128     
129     /**
130      * Add all VM's in the specified list to the VM definitions managed by this container.
131      * <p>
132      * If distinguishing valid from invalid VMs is important, the specified VMs must
133      * have already had their install locations set. An invalid VM is one whose install
134      * location doesn't exist.
135      * </p>
136      *
137      * @param vmList a list of VMs to be added to this container
138      */

139     public void addVMList(List JavaDoc vmList) {
140         Iterator JavaDoc iterator = vmList.iterator();
141         while (iterator.hasNext()) {
142             IVMInstall vm = (IVMInstall) iterator.next();
143             addVM(vm);
144         }
145     }
146
147     /**
148      * Return a mapping of VM install types to lists of VMs. The keys of this map are instances of
149      * <code>IVMInstallType</code>. The values are instances of <code>java.util.List</code>
150      * which contain instances of <code>IVMInstall</code>.
151      *
152      * @return Map the mapping of VM install types to lists of VMs
153      */

154     public Map JavaDoc getVMTypeToVMMap() {
155         return fVMTypeToVMMap;
156     }
157     
158     /**
159      * Return a list of all VMs in this container, including any invalid VMs. An invalid
160      * VM is one whose install location does not exist on the file system.
161      * The order of the list is not specified.
162      *
163      * @return List the data structure containing all VMs managed by this container
164      */

165     public List JavaDoc getVMList() {
166         return fVMList;
167     }
168     
169     /**
170      * Return a list of all valid VMs in this container. A valid VM is one whose install
171      * location exists on the file system. The order of the list is not specified.
172      *
173      * @return List
174      */

175     public List JavaDoc getValidVMList() {
176         List JavaDoc vms = getVMList();
177         List JavaDoc resultList = new ArrayList JavaDoc(vms.size());
178         resultList.addAll(vms);
179         resultList.removeAll(fInvalidVMList);
180         return resultList;
181     }
182     
183     /**
184      * Returns the composite ID for the default VM. The composite ID consists
185      * of an ID for the VM install type together with an ID for VM. This is
186      * necessary because VM ids by themselves are not necessarily unique across
187      * VM install types.
188      *
189      * @return String returns the composite ID of the current default VM
190      */

191     public String JavaDoc getDefaultVMInstallCompositeID(){
192         return fDefaultVMInstallCompositeID;
193     }
194     
195     /**
196      * Sets the composite ID for the default VM. The composite ID consists
197      * of an ID for the VM install type together with an ID for VM. This is
198      * necessary because VM ids by themselves are not necessarily unique across
199      * VM install types.
200      *
201      * @param id identifies the new default VM using a composite ID
202      */

203     public void setDefaultVMInstallCompositeID(String JavaDoc id){
204         fDefaultVMInstallCompositeID = id;
205     }
206     
207     /**
208      * Return the default VM's connector type ID.
209      *
210      * @return String the current value of the default VM's connector type ID
211      */

212     public String JavaDoc getDefaultVMInstallConnectorTypeID() {
213         return fDefaultVMInstallConnectorTypeID;
214     }
215     
216     /**
217      * Set the default VM's connector type ID.
218      *
219      * @param id the new value of the default VM's connector type ID
220      */

221     public void setDefaultVMInstallConnectorTypeID(String JavaDoc id){
222         fDefaultVMInstallConnectorTypeID = id;
223     }
224     
225     /**
226      * Return the VM definitions contained in this object as a String of XML. The String
227      * is suitable for storing in the workbench preferences.
228      * <p>
229      * The resulting XML is compatible with the static method <code>parseXMLIntoContainer</code>.
230      * </p>
231      * @return String the results of flattening this object into XML
232      * @throws IOException if this method fails. Reasons include:<ul>
233      * <li>serialization of the XML document failed</li>
234      * </ul>
235      * @throws ParserConfigurationException if creation of the XML document failed
236      * @throws TransformerException if serialization of the XML document failed
237      */

238     public String JavaDoc getAsXML() throws ParserConfigurationException JavaDoc, IOException JavaDoc, TransformerException JavaDoc {
239         
240         // Create the Document and the top-level node
241
Document JavaDoc doc = LaunchingPlugin.getDocument();
242         Element JavaDoc config = doc.createElement("vmSettings"); //$NON-NLS-1$
243
doc.appendChild(config);
244         
245         // Set the defaultVM attribute on the top-level node
246
if (getDefaultVMInstallCompositeID() != null) {
247             config.setAttribute("defaultVM", getDefaultVMInstallCompositeID()); //$NON-NLS-1$
248
}
249         
250         // Set the defaultVMConnector attribute on the top-level node
251
if (getDefaultVMInstallConnectorTypeID() != null) {
252             config.setAttribute("defaultVMConnector", getDefaultVMInstallConnectorTypeID()); //$NON-NLS-1$
253
}
254                 
255         // Create a node for each install type represented in this container
256
Set JavaDoc vmInstallTypeSet = getVMTypeToVMMap().keySet();
257         Iterator JavaDoc keyIterator = vmInstallTypeSet.iterator();
258         while (keyIterator.hasNext()) {
259             IVMInstallType vmInstallType = (IVMInstallType) keyIterator.next();
260             Element JavaDoc vmTypeElement = vmTypeAsElement(doc, vmInstallType);
261             config.appendChild(vmTypeElement);
262         }
263         
264         // Serialize the Document and return the resulting String
265
return LaunchingPlugin.serializeDocument(doc);
266     }
267     
268     /**
269      * Create and return a node for the specified VM install type in the specified Document.
270      */

271     private Element JavaDoc vmTypeAsElement(Document JavaDoc doc, IVMInstallType vmType) {
272         
273         // Create a node for the vm type and set its 'id' attribute
274
Element JavaDoc element= doc.createElement("vmType"); //$NON-NLS-1$
275
element.setAttribute("id", vmType.getId()); //$NON-NLS-1$
276

277         // For each vm of the specified type, create a subordinate node for it
278
List JavaDoc vmList = (List JavaDoc) getVMTypeToVMMap().get(vmType);
279         Iterator JavaDoc vmIterator = vmList.iterator();
280         while (vmIterator.hasNext()) {
281             IVMInstall vm = (IVMInstall) vmIterator.next();
282             Element JavaDoc vmElement = vmAsElement(doc, vm);
283             element.appendChild(vmElement);
284         }
285         
286         return element;
287     }
288     
289     /**
290      * Create and return a node for the specified VM in the specified Document.
291      */

292     private Element JavaDoc vmAsElement(Document JavaDoc doc, IVMInstall vm) {
293         
294         // Create the node for the VM and set its 'id' & 'name' attributes
295
Element JavaDoc element= doc.createElement("vm"); //$NON-NLS-1$
296
element.setAttribute("id", vm.getId()); //$NON-NLS-1$
297
element.setAttribute("name", vm.getName()); //$NON-NLS-1$
298

299         // Determine and set the 'path' attribute for the VM
300
String JavaDoc installPath= ""; //$NON-NLS-1$
301
File JavaDoc installLocation= vm.getInstallLocation();
302         if (installLocation != null) {
303             installPath= installLocation.getAbsolutePath();
304         }
305         element.setAttribute("path", installPath); //$NON-NLS-1$
306

307         // If the 'libraryLocations' attribute is specified, create a node for it
308
LibraryLocation[] libraryLocations= vm.getLibraryLocations();
309         if (libraryLocations != null) {
310             Element JavaDoc libLocationElement = libraryLocationsAsElement(doc, libraryLocations);
311             element.appendChild(libLocationElement);
312         }
313         
314         // Java doc location
315
URL JavaDoc url = vm.getJavadocLocation();
316         if (url != null) {
317             element.setAttribute("javadocURL", url.toExternalForm()); //$NON-NLS-1$
318
}
319         
320         if (vm instanceof IVMInstall2) {
321             String JavaDoc vmArgs = ((IVMInstall2)vm).getVMArgs();
322             if (vmArgs != null && vmArgs.length() > 0) {
323                 element.setAttribute("vmargs", vmArgs); //$NON-NLS-1$
324
}
325         } else {
326             String JavaDoc[] vmArgs = vm.getVMArguments();
327             if (vmArgs != null && vmArgs.length > 0) {
328                 StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
329                 for (int i = 0; i < vmArgs.length; i++) {
330                     buffer.append(vmArgs[i] + " "); //$NON-NLS-1$
331
}
332                 element.setAttribute("vmargs", buffer.toString()); //$NON-NLS-1$
333
}
334         }
335         
336         return element;
337     }
338     
339     /**
340      * Create and return a 'libraryLocations' node. This node owns subordinate nodes that
341      * list individual library locations.
342      */

343     private static Element JavaDoc libraryLocationsAsElement(Document JavaDoc doc, LibraryLocation[] locations) {
344         Element JavaDoc root = doc.createElement("libraryLocations"); //$NON-NLS-1$
345
for (int i = 0; i < locations.length; i++) {
346             Element JavaDoc element = doc.createElement("libraryLocation"); //$NON-NLS-1$
347
element.setAttribute("jreJar", locations[i].getSystemLibraryPath().toString()); //$NON-NLS-1$
348
element.setAttribute("jreSrc", locations[i].getSystemLibrarySourcePath().toString()); //$NON-NLS-1$
349

350             IPath packageRootPath = locations[i].getPackageRootPath();
351             if (packageRootPath != null) {
352                 element.setAttribute("pkgRoot", packageRootPath.toString()); //$NON-NLS-1$
353
}
354             
355             URL JavaDoc url= locations[i].getJavadocLocation();
356             if (url != null) {
357                 element.setAttribute("jreJavadoc", url.toExternalForm()); //$NON-NLS-1$
358
}
359             root.appendChild(element);
360         }
361         return root;
362     }
363     
364     public static VMDefinitionsContainer parseXMLIntoContainer(InputStream JavaDoc inputStream) throws IOException JavaDoc {
365         VMDefinitionsContainer container = new VMDefinitionsContainer();
366         parseXMLIntoContainer(inputStream, container);
367         return container;
368     }
369             
370     /**
371      * Parse the VM definitions contained in the specified InputStream into the
372      * specified container.
373      * <p>
374      * The VMs in the returned container are instances of <code>VMStandin</code>.
375      * </p>
376      * <p>
377      * This method has no side-effects. That is, no notifications are sent for VM adds,
378      * changes, deletes, and the workbench preferences are not affected.
379      * </p>
380      * <p>
381      * If the <code>getAsXML</code> method is called on the returned container object,
382      * the resulting XML will be semantically equivalent (though not necessarily syntactically equivalent) as
383      * the XML contained in <code>inputStream</code>.
384      * </p>
385      * @param inputStream the <code>InputStream</code> containing XML that declares a set of VMs and a default VM
386      * @param container the container to add the VM defs to
387      * @return VMDefinitionsContainer a container for the VM objects declared in <code>inputStream</code>
388      * @throws IOException if this method fails. Reasons include:<ul>
389      * <li>the XML in <code>inputStream</code> was badly formatted</li>
390      * <li>the top-level node was not 'vmSettings'</li>
391      * </ul>
392      * @since 3.2
393      */

394     public static void parseXMLIntoContainer(InputStream JavaDoc inputStream, VMDefinitionsContainer container) throws IOException JavaDoc {
395
396         // Wrapper the stream for efficient parsing
397
InputStream JavaDoc stream= new BufferedInputStream JavaDoc(inputStream);
398
399         // Do the parsing and obtain the top-level node
400
Element JavaDoc config= null;
401         try {
402             DocumentBuilder JavaDoc parser= DocumentBuilderFactory.newInstance().newDocumentBuilder();
403             parser.setErrorHandler(new DefaultHandler JavaDoc());
404             config = parser.parse(new InputSource JavaDoc(stream)).getDocumentElement();
405         } catch (SAXException JavaDoc e) {
406             throw new IOException JavaDoc(LaunchingMessages.JavaRuntime_badFormat);
407         } catch (ParserConfigurationException JavaDoc e) {
408             stream.close();
409             throw new IOException JavaDoc(LaunchingMessages.JavaRuntime_badFormat);
410         } finally {
411             stream.close();
412         }
413         
414         // If the top-level node wasn't what we expected, bail out
415
if (!config.getNodeName().equalsIgnoreCase("vmSettings")) { //$NON-NLS-1$
416
throw new IOException JavaDoc(LaunchingMessages.JavaRuntime_badFormat);
417         }
418         
419         // Populate the default VM-related fields
420
container.setDefaultVMInstallCompositeID(config.getAttribute("defaultVM")); //$NON-NLS-1$
421
container.setDefaultVMInstallConnectorTypeID(config.getAttribute("defaultVMConnector")); //$NON-NLS-1$
422

423         // Traverse the parsed structure and populate the VMType to VM Map
424
NodeList JavaDoc list = config.getChildNodes();
425         int length = list.getLength();
426         for (int i = 0; i < length; ++i) {
427             Node JavaDoc node = list.item(i);
428             short type = node.getNodeType();
429             if (type == Node.ELEMENT_NODE) {
430                 Element JavaDoc vmTypeElement = (Element JavaDoc) node;
431                 if (vmTypeElement.getNodeName().equalsIgnoreCase("vmType")) { //$NON-NLS-1$
432
populateVMTypes(vmTypeElement, container);
433                 }
434             }
435         }
436     }
437     
438     /**
439      * For the specified vm type node, parse all subordinate VM definitions and add them
440      * to the specified container.
441      */

442     private static void populateVMTypes(Element JavaDoc vmTypeElement, VMDefinitionsContainer container) {
443         
444         // Retrieve the 'id' attribute and the corresponding VM type object
445
String JavaDoc id = vmTypeElement.getAttribute("id"); //$NON-NLS-1$
446
IVMInstallType vmType= JavaRuntime.getVMInstallType(id);
447         if (vmType != null) {
448             // For each VM child node, populate the container with a subordinate node
449
NodeList JavaDoc vmNodeList = vmTypeElement.getElementsByTagName("vm"); //$NON-NLS-1$
450
for (int i = 0; i < vmNodeList.getLength(); ++i) {
451                 populateVMForType(vmType, (Element JavaDoc) vmNodeList.item(i), container);
452             }
453         } else {
454             LaunchingPlugin.log("VM type element with unknown id."); //$NON-NLS-1$
455
}
456     }
457
458     /**
459      * Parse the specified VM node, create a VMStandin for it, and add this to the
460      * specified container.
461      */

462     private static void populateVMForType(IVMInstallType vmType, Element JavaDoc vmElement, VMDefinitionsContainer container) {
463         String JavaDoc id= vmElement.getAttribute("id"); //$NON-NLS-1$
464
if (id != null) {
465             
466             // Retrieve the 'path' attribute. If none, skip this node.
467
String JavaDoc installPath= vmElement.getAttribute("path"); //$NON-NLS-1$
468
if (installPath == null) {
469                 return;
470             }
471                         
472             // Create a VMStandin for the node and set its 'name' & 'installLocation' attributes
473
VMStandin vmStandin = new VMStandin(vmType, id);
474             vmStandin.setName(vmElement.getAttribute("name")); //$NON-NLS-1$
475
File JavaDoc installLocation= new File JavaDoc(installPath);
476             vmStandin.setInstallLocation(installLocation);
477             container.addVM(vmStandin);
478             
479             // Look for subordinate nodes. These may be 'libraryLocation',
480
// 'libraryLocations' or 'versionInfo'.
481
NodeList JavaDoc list = vmElement.getChildNodes();
482             int length = list.getLength();
483             for (int i = 0; i < length; ++i) {
484                 Node JavaDoc node = list.item(i);
485                 short type = node.getNodeType();
486                 if (type == Node.ELEMENT_NODE) {
487                     Element JavaDoc subElement = (Element JavaDoc)node;
488                     String JavaDoc subElementName = subElement.getNodeName();
489                     if (subElementName.equals("libraryLocation")) { //$NON-NLS-1$
490
LibraryLocation loc = getLibraryLocation(subElement);
491                         vmStandin.setLibraryLocations(new LibraryLocation[]{loc});
492                         break;
493                     } else if (subElementName.equals("libraryLocations")) { //$NON-NLS-1$
494
setLibraryLocations(vmStandin, subElement);
495                         break;
496                     }
497                 }
498             }
499             
500             // javadoc URL
501
String JavaDoc externalForm = vmElement.getAttribute("javadocURL"); //$NON-NLS-1$
502
if (externalForm != null && externalForm.length() > 0) {
503                 try {
504                     vmStandin.setJavadocLocation(new URL JavaDoc(externalForm));
505                 } catch (MalformedURLException JavaDoc e) {
506                     LaunchingPlugin.log(e);
507                 }
508             }
509             
510             // vm Arguments
511
String JavaDoc vmArgs = vmElement.getAttribute("vmargs"); //$NON-NLS-1$
512
if (vmArgs != null && vmArgs.length() >0) {
513                 vmStandin.setVMArgs(vmArgs);
514             }
515         } else {
516             LaunchingPlugin.log("id attribute missing from VM element specification."); //$NON-NLS-1$
517
}
518     }
519     
520     /**
521      * Create & return a LibraryLocation object populated from the attribute values
522      * in the specified node.
523      */

524     private static LibraryLocation getLibraryLocation(Element JavaDoc libLocationElement) {
525         String JavaDoc jreJar= libLocationElement.getAttribute("jreJar"); //$NON-NLS-1$
526
String JavaDoc jreSrc= libLocationElement.getAttribute("jreSrc"); //$NON-NLS-1$
527
String JavaDoc pkgRoot= libLocationElement.getAttribute("pkgRoot"); //$NON-NLS-1$
528
String JavaDoc jreJavadoc= libLocationElement.getAttribute("jreJavadoc"); //$NON-NLS-1$
529
URL JavaDoc javadocURL= null;
530         if (jreJavadoc.length() == 0) {
531             jreJavadoc= null;
532         } else {
533             try {
534                 javadocURL= new URL JavaDoc(jreJavadoc);
535             } catch (MalformedURLException JavaDoc e) {
536                 LaunchingPlugin.log("Library location element is specified incorrectly."); //$NON-NLS-1$
537
}
538         }
539         if (jreJar != null && jreSrc != null && pkgRoot != null) {
540             return new LibraryLocation(new Path(jreJar), new Path(jreSrc), new Path(pkgRoot), javadocURL);
541         }
542         LaunchingPlugin.log("Library location element is specified incorrectly."); //$NON-NLS-1$
543
return null;
544     }
545     
546     /**
547      * Set the LibraryLocations on the specified VM, by extracting the subordinate
548      * nodes from the specified 'lirbaryLocations' node.
549      */

550     private static void setLibraryLocations(IVMInstall vm, Element JavaDoc libLocationsElement) {
551         NodeList JavaDoc list = libLocationsElement.getChildNodes();
552         int length = list.getLength();
553         List JavaDoc locations = new ArrayList JavaDoc(length);
554         for (int i = 0; i < length; ++i) {
555             Node JavaDoc node = list.item(i);
556             short type = node.getNodeType();
557             if (type == Node.ELEMENT_NODE) {
558                 Element JavaDoc libraryLocationElement= (Element JavaDoc)node;
559                 if (libraryLocationElement.getNodeName().equals("libraryLocation")) { //$NON-NLS-1$
560
locations.add(getLibraryLocation(libraryLocationElement));
561                 }
562             }
563         }
564         vm.setLibraryLocations((LibraryLocation[])locations.toArray(new LibraryLocation[locations.size()]));
565     }
566     
567     /**
568      * Removes the VM from this container.
569      *
570      * @param vm vm intall
571      */

572     public void removeVM(IVMInstall vm) {
573         fVMList.remove(vm);
574         fInvalidVMList.remove(vm);
575         List JavaDoc list = (List JavaDoc) fVMTypeToVMMap.get(vm.getVMInstallType());
576         if (list != null) {
577             list.remove(vm);
578         }
579     }
580         
581 }
582
Popular Tags