1 19 20 package org.netbeans.modules.java.j2seplatform.platformdefinition; 21 22 import java.beans.*; 23 import java.io.*; 24 import java.lang.ref.*; 25 import java.util.*; 26 import java.util.List ; 27 import java.net.URL ; 28 import java.net.MalformedURLException ; 29 import java.net.URI ; 30 import java.util.logging.Level ; 31 import java.util.logging.Logger ; 32 33 import org.netbeans.api.project.ProjectManager; 34 import org.netbeans.spi.project.support.ant.EditableProperties; 35 import org.netbeans.spi.project.support.ant.PropertyUtils; 36 37 import org.openide.ErrorManager; 38 import org.openide.modules.SpecificationVersion; 39 import org.openide.cookies.*; 40 import org.openide.filesystems.*; 41 import org.openide.filesystems.FileChangeAdapter; 42 import org.openide.loaders.*; 43 import org.openide.nodes.Node; 44 import org.openide.util.*; 45 import org.openide.util.lookup.*; 46 import org.openide.xml.*; 47 import org.w3c.dom.Document ; 48 import org.w3c.dom.Element ; 49 50 import org.xml.sax.*; 51 52 import org.netbeans.api.java.platform.*; 53 import org.netbeans.api.java.classpath.ClassPath; 54 import org.netbeans.modules.java.j2seplatform.wizard.J2SEWizardIterator; 55 56 61 public class PlatformConvertor implements Environment.Provider, InstanceCookie.Of, PropertyChangeListener, Runnable , InstanceContent.Convertor { 62 63 private static final String CLASSIC = "classic"; private static final String MODERN = "modern"; private static final String JAVAC13 = "javac1.3"; static final String [] IMPORTANT_TOOLS = { 67 "javac", "java", "javadoc", }; 73 74 private static final String PLATFORM_DTD_ID = "-//NetBeans//DTD Java PlatformDefinition 1.0//EN"; 76 private PlatformConvertor() {} 77 78 public static PlatformConvertor createProvider(FileObject reg) { 79 return new PlatformConvertor(); 80 } 81 82 public Lookup getEnvironment(DataObject obj) { 83 return new PlatformConvertor((XMLDataObject)obj).getLookup(); 84 } 85 86 InstanceContent cookies = new InstanceContent(); 87 88 private XMLDataObject holder; 89 90 private boolean defaultPlatform; 91 92 private Lookup lookup; 93 94 private RequestProcessor.Task saveTask; 95 96 private Reference refPlatform = new WeakReference(null); 97 98 private LinkedList keepAlive = new LinkedList(); 99 100 private PlatformConvertor(XMLDataObject object) { 101 this.holder = object; 102 this.holder.getPrimaryFile().addFileChangeListener( new FileChangeAdapter () { 103 public void fileDeleted (final FileEvent fe) { 104 if (!defaultPlatform) { 105 try { 106 ProjectManager.mutex().writeAccess( new Mutex.ExceptionAction () { 107 public Object run () throws IOException { 108 String systemName = fe.getFile().getName(); 109 String propPrefix = "platforms." + systemName + "."; boolean changed = false; 111 EditableProperties props = PropertyUtils.getGlobalProperties(); 112 for (Iterator it = props.keySet().iterator(); it.hasNext(); ) { 113 String key = (String ) it.next (); 114 if (key.startsWith(propPrefix)) { 115 it.remove(); 116 changed =true; 117 } 118 } 119 if (changed) { 120 PropertyUtils.putGlobalProperties(props); 121 } 122 return null; 123 } 124 }); 125 } catch (MutexException e) { 126 ErrorManager.getDefault().notify(e); 127 } 128 } 129 } 130 }); 131 cookies = new InstanceContent(); 132 cookies.add(this); 133 lookup = new AbstractLookup(cookies); 134 cookies.add(Node.class, this); 135 } 136 137 Lookup getLookup() { 138 return lookup; 139 } 140 141 public Class instanceClass() { 142 return JavaPlatform.class; 143 } 144 145 public Object instanceCreate() throws java.io.IOException , ClassNotFoundException { 146 synchronized (this) { 147 Object o = refPlatform.get(); 148 if (o != null) 149 return o; 150 H handler = new H(); 151 try { 152 XMLReader reader = XMLUtil.createXMLReader(); 153 InputSource is = new org.xml.sax.InputSource ( 154 holder.getPrimaryFile().getInputStream()); 155 is.setSystemId(holder.getPrimaryFile().getURL().toExternalForm()); 156 reader.setContentHandler(handler); 157 reader.setErrorHandler(handler); 158 reader.setEntityResolver(handler); 159 160 reader.parse(is); 161 } catch (SAXException ex) { 162 Exception x = ex.getException(); 163 ex.printStackTrace(); 164 if (x instanceof java.io.IOException ) 165 throw (IOException)x; 166 else 167 throw new java.io.IOException (ex.getMessage()); 168 } 169 170 JavaPlatform inst = createPlatform(handler); 171 refPlatform = new WeakReference(inst); 172 return inst; 173 } 174 } 175 176 JavaPlatform createPlatform(H handler) { 177 JavaPlatform p; 178 179 if (handler.isDefault) { 180 p = DefaultPlatformImpl.create (handler.properties, handler.sources, handler.javadoc); 181 defaultPlatform = true; 182 } else { 183 p = new J2SEPlatformImpl(handler.name,handler.installFolders, handler.properties, handler.sysProperties,handler.sources, handler.javadoc); 184 defaultPlatform = false; 185 } 186 p.addPropertyChangeListener(this); 187 return p; 188 } 189 190 public String instanceName() { 191 return holder.getName(); 192 } 193 194 public boolean instanceOf(Class type) { 195 return (type.isAssignableFrom(JavaPlatform.class)); 196 } 197 198 static int DELAY = 2000; 199 200 public void propertyChange(PropertyChangeEvent evt) { 201 synchronized (this) { 202 if (saveTask == null) 203 saveTask = RequestProcessor.getDefault().create(this); 204 } 205 synchronized (this) { 206 keepAlive.add(evt); 207 } 208 saveTask.schedule(DELAY); 209 } 210 211 public void run() { 212 PropertyChangeEvent e; 213 214 synchronized (this) { 215 e = (PropertyChangeEvent)keepAlive.removeFirst(); 216 } 217 JavaPlatform plat = (JavaPlatform)e.getSource(); 218 try { 219 holder.getPrimaryFile().getFileSystem().runAtomicAction( 220 new W(plat, holder, defaultPlatform)); 221 } catch (java.io.IOException ex) { 222 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); 223 } 224 } 225 226 public Object convert(Object obj) { 227 if (obj == Node.class) { 228 try { 229 J2SEPlatformImpl p = (J2SEPlatformImpl) instanceCreate(); 230 return new J2SEPlatformNode (p,this.holder); 231 } catch (IOException ex) { 232 ErrorManager.getDefault().notify(ex); 233 } catch (ClassNotFoundException ex) { 234 ErrorManager.getDefault().notify(ex); 235 } catch (Exception ex) { 236 ErrorManager.getDefault().notify(ex); 237 } 238 } 239 return null; 240 } 241 242 public String displayName(Object obj) { 243 return ((Class )obj).getName(); 244 } 245 246 public String id(Object obj) { 247 return obj.toString(); 248 } 249 250 public Class type(Object obj) { 251 return (Class )obj; 252 } 253 254 public static DataObject create(final JavaPlatform plat, final DataFolder f, final String idName) throws IOException { 255 W w = new W(plat, f, idName); 256 f.getPrimaryFile().getFileSystem().runAtomicAction(w); 257 try { 258 ProjectManager.mutex().writeAccess( 259 new Mutex.ExceptionAction () { 260 public Object run () throws Exception { 261 EditableProperties props = PropertyUtils.getGlobalProperties(); 262 generatePlatformProperties(plat, idName, props); 263 PropertyUtils.putGlobalProperties (props); 264 return null; 265 } 266 }); 267 } catch (MutexException me) { 268 Exception originalException = me.getException(); 269 if (originalException instanceof RuntimeException ) { 270 throw (RuntimeException ) originalException; 271 } 272 else if (originalException instanceof IOException) { 273 throw (IOException) originalException; 274 } 275 else 276 { 277 throw new IllegalStateException (); } 279 } 280 return w.holder; 281 } 282 283 public static void generatePlatformProperties (JavaPlatform platform, String systemName, EditableProperties props) throws IOException { 284 String homePropName = createName(systemName,"home"); String bootClassPathPropName = createName(systemName,"bootclasspath"); String compilerType= createName (systemName,"compiler"); if (props.getProperty(homePropName) != null || props.getProperty(bootClassPathPropName) != null 288 || props.getProperty(compilerType)!=null) { 289 String msg = NbBundle.getMessage(J2SEWizardIterator.class,"ERROR_InvalidName"); throw (IllegalStateException )ErrorManager.getDefault().annotate( 292 new IllegalStateException (msg), ErrorManager.USER, null, msg,null, null); 293 } 294 Collection installFolders = platform.getInstallFolders(); 295 if (installFolders.size()>0) { 296 File jdkHome = FileUtil.toFile ((FileObject)installFolders.iterator().next()); 297 props.setProperty(homePropName, jdkHome.getAbsolutePath()); 298 ClassPath bootCP = platform.getBootstrapLibraries(); 299 StringBuffer sbootcp = new StringBuffer (); 300 for (Iterator it = bootCP.entries().iterator(); it.hasNext();) { 301 ClassPath.Entry entry = (ClassPath.Entry) it.next(); 302 URL url = entry.getURL(); 303 if ("jar".equals(url.getProtocol())) { url = FileUtil.getArchiveFile(url); 305 } 306 File root = new File (URI.create(url.toExternalForm())); 307 if (sbootcp.length()>0) { 308 sbootcp.append(File.pathSeparator); 309 } 310 sbootcp.append(normalizePath(root, jdkHome, homePropName)); 311 } 312 props.setProperty(bootClassPathPropName,sbootcp.toString()); props.setProperty(compilerType,getCompilerType(platform)); 314 for (int i = 0; i < IMPORTANT_TOOLS.length; i++) { 315 String name = IMPORTANT_TOOLS[i]; 316 FileObject tool = platform.findTool(name); 317 if (tool != null) { 318 if (!isDefaultLocation(tool, platform.getInstallFolders())) { 319 String toolName = createName(systemName, name); 320 props.setProperty(toolName, normalizePath(getToolPath(tool), jdkHome, homePropName)); 321 } 322 } else { 323 throw new BrokenPlatformException (name); 324 } 325 } 326 } 327 } 328 329 public static String createName (String platName, String propType) { 330 return "platforms." + platName + "." + propType; } 332 333 private static String getCompilerType (JavaPlatform platform) { 334 assert platform != null; 335 String prop = (String ) platform.getSystemProperties().get("java.specification.version"); assert prop != null; 337 SpecificationVersion specificationVersion = new SpecificationVersion (prop); 338 SpecificationVersion jdk13 = new SpecificationVersion("1.3"); int c = specificationVersion.compareTo (jdk13); 340 if (c<0) { 341 return CLASSIC; 342 } 343 else if (c == 0) { 344 return JAVAC13; 345 } 346 else { 347 return MODERN; 348 } 349 } 350 351 private static boolean isDefaultLocation (FileObject tool, Collection installFolders) { 352 assert tool != null && installFolders != null; 353 if (installFolders.size()!=1) 354 return false; 355 FileObject root = (FileObject)installFolders.iterator().next(); 356 String relativePath = FileUtil.getRelativePath(root,tool); 357 if (relativePath == null) { 358 return false; 359 } 360 StringTokenizer tk = new StringTokenizer(relativePath, "/"); 361 return (tk.countTokens()== 2 && "bin".equals(tk.nextToken())); 362 } 363 364 365 private static File getToolPath (FileObject tool) throws IOException { 366 assert tool != null; 367 return new File (URI.create(tool.getURL().toExternalForm())); 368 } 369 370 private static String normalizePath (File path, File jdkHome, String propName) { 371 String jdkLoc = jdkHome.getAbsolutePath(); 372 if (!jdkLoc.endsWith(File.separator)) { 373 jdkLoc = jdkLoc + File.separator; 374 } 375 String loc = path.getAbsolutePath(); 376 if (loc.startsWith(jdkLoc)) { 377 return "${"+propName+"}"+File.separator+loc.substring(jdkLoc.length()); } 379 else { 380 return loc; 381 } 382 } 383 384 public static class BrokenPlatformException extends IOException { 385 386 private final String toolName; 387 388 public BrokenPlatformException (final String toolName) { 389 super ("Cannot locate " + toolName + " command"); this.toolName = toolName; 391 } 392 393 public String getMissingTool () { 394 return this.toolName; 395 } 396 397 } 398 399 static class W implements FileSystem.AtomicAction { 400 JavaPlatform instance; 401 MultiDataObject holder; 402 String name; 403 DataFolder f; 404 boolean defaultPlatform; 405 406 W(JavaPlatform instance, MultiDataObject holder, boolean defaultPlatform) { 407 this.instance = instance; 408 this.holder = holder; 409 this.defaultPlatform = defaultPlatform; 410 } 411 412 W(JavaPlatform instance, DataFolder f, String n) { 413 this.instance = instance; 414 this.name = n; 415 this.f = f; 416 this.defaultPlatform = false; 417 } 418 419 public void run() throws java.io.IOException { 420 FileLock lck; 421 FileObject data; 422 423 424 ByteArrayOutputStream buffer = new ByteArrayOutputStream (); 425 try { 426 write (buffer); 427 } finally { 428 buffer.close(); 429 } 430 if (holder != null) { 431 data = holder.getPrimaryEntry().getFile(); 432 lck = holder.getPrimaryEntry().takeLock(); 433 } else { 434 FileObject folder = f.getPrimaryFile(); 435 String fn = FileUtil.findFreeFileName(folder, name, "xml"); 436 data = folder.createData(fn, "xml"); 437 lck = data.lock(); 438 } 439 try { 440 OutputStream out = data.getOutputStream(lck); 441 try { 442 out.write(buffer.toByteArray()); 443 out.flush(); 444 } finally { 445 out.close(); 446 } 447 } finally { 448 lck.releaseLock(); 449 } 450 if (holder == null) { 451 holder = (MultiDataObject)DataObject.find(data); 452 } 453 } 454 455 void write(final OutputStream out) throws IOException { 456 final Map props = instance.getProperties(); 457 final Map sysProps = instance.getSystemProperties(); 458 final Document doc = XMLUtil.createDocument(ELEMENT_PLATFORM,null,PLATFORM_DTD_ID,"http://www.netbeans.org/dtds/java-platformdefinition-1_0.dtd"); final Element platformElement = doc.getDocumentElement(); 460 platformElement.setAttribute(ATTR_PLATFORM_NAME,instance.getDisplayName()); 461 platformElement.setAttribute(ATTR_PLATFORM_DEFAULT,defaultPlatform ? "yes" : "no"); final Element propsElement = doc.createElement(ELEMENT_PROPERTIES); 463 writeProperties(props, propsElement, doc); 464 platformElement.appendChild(propsElement); 465 if (!defaultPlatform) { 466 final Element sysPropsElement = doc.createElement(ELEMENT_SYSPROPERTIES); 467 writeProperties(sysProps, sysPropsElement, doc); 468 platformElement.appendChild(sysPropsElement); 469 final Element jdkHomeElement = doc.createElement(ELEMENT_JDKHOME); 470 for (Iterator it = instance.getInstallFolders().iterator(); it.hasNext();) { 471 URL url = ((FileObject)it.next ()).getURL(); 472 final Element resourceElement = doc.createElement(ELEMENT_RESOURCE); 473 resourceElement.appendChild(doc.createTextNode(url.toExternalForm())); 474 jdkHomeElement.appendChild(resourceElement); 475 } 476 platformElement.appendChild(jdkHomeElement); 477 } 478 List pl = this.instance.getSourceFolders().entries(); 479 if (pl.size()>0 && shouldWriteSources ()) { 480 final Element sourcesElement = doc.createElement (ELEMENT_SOURCEPATH); 481 for (Iterator it = pl.iterator(); it.hasNext();) { 482 URL url = ((ClassPath.Entry)it.next ()).getURL(); 483 final Element resourceElement = doc.createElement (ELEMENT_RESOURCE); 484 resourceElement.appendChild(doc.createTextNode(url.toExternalForm())); 485 sourcesElement.appendChild(resourceElement); 486 } 487 platformElement.appendChild(sourcesElement); 488 } 489 pl = this.instance.getJavadocFolders(); 490 if (pl.size()>0 && shouldWriteJavadoc ()) { 491 final Element javadocElement = doc.createElement(ELEMENT_JAVADOC); 492 for (Iterator it = pl.iterator(); it.hasNext();) { 493 URL url = (URL ) it.next (); 494 final Element resourceElement = doc.createElement(ELEMENT_RESOURCE); 495 resourceElement.appendChild(doc.createTextNode(url.toExternalForm())); 496 javadocElement.appendChild(resourceElement); 497 } 498 platformElement.appendChild(javadocElement); 499 } 500 XMLUtil.write(doc, out, "UTF8"); } 502 503 void writeProperties(final Map props, final Element element, final Document doc) throws IOException { 504 final Collection sortedProps = new TreeSet(props.keySet()); 505 for (Iterator it = sortedProps.iterator(); it.hasNext(); ) { 506 final String n = (String )it.next(); 507 final String val = (String )props.get(n); 508 try { 509 XMLUtil.toAttributeValue(n); 510 XMLUtil.toAttributeValue(val); 511 final Element propElement = doc.createElement(ELEMENT_PROPERTY); 512 propElement.setAttribute(ATTR_PROPERTY_NAME,n); 513 propElement.setAttribute(ATTR_PROPERTY_VALUE,val); 514 element.appendChild(propElement); 515 } catch (CharConversionException e) { 516 Logger.getLogger("global").log(Level.WARNING,"Cannot store property: " + n + " value: " + val); } 518 } 519 } 520 521 private boolean shouldWriteSources () { 522 if (defaultPlatform) { 523 assert this.instance instanceof DefaultPlatformImpl; 524 DefaultPlatformImpl dp = (DefaultPlatformImpl) this.instance; 525 List sfEntries = dp.getSourceFolders().entries(); 526 List defaultSf = DefaultPlatformImpl.getSources (FileUtil.normalizeFile(new File((String )dp.getSystemProperties().get("jdk.home")))); if (defaultSf == null || sfEntries.size() != defaultSf.size()) { 528 return true; 529 } 530 Iterator sfit = sfEntries.iterator(); 531 Iterator defif = defaultSf.iterator(); 532 while (sfit.hasNext()) { 533 ClassPath.Entry entry = (ClassPath.Entry) sfit.next (); 534 URL url = (URL ) defif.next(); 535 if (!url.equals(entry.getURL())) { 536 return true; 537 } 538 } 539 return false; 540 } 541 return true; 542 } 543 544 private boolean shouldWriteJavadoc () { 545 if (defaultPlatform) { 546 assert this.instance instanceof DefaultPlatformImpl; 547 DefaultPlatformImpl dp = (DefaultPlatformImpl) this.instance; 548 List jdf = dp.getJavadocFolders(); 549 List defaultJdf = DefaultPlatformImpl.getJavadoc (FileUtil.normalizeFile(new File((String )dp.getSystemProperties().get("jdk.home")))); return defaultJdf == null || !jdf.equals (defaultJdf); 551 } 552 return true; 553 } 554 } 555 556 static final String ELEMENT_PROPERTIES = "properties"; static final String ELEMENT_SYSPROPERTIES = "sysproperties"; static final String ELEMENT_PROPERTY = "property"; static final String ELEMENT_PLATFORM = "platform"; static final String ELEMENT_JDKHOME = "jdkhome"; static final String ELEMENT_SOURCEPATH = "sources"; static final String ELEMENT_JAVADOC = "javadoc"; static final String ELEMENT_RESOURCE = "resource"; static final String ATTR_PLATFORM_NAME = "name"; static final String ATTR_PLATFORM_DEFAULT = "default"; static final String ATTR_PROPERTY_NAME = "name"; static final String ATTR_PROPERTY_VALUE = "value"; 569 static class H extends org.xml.sax.helpers.DefaultHandler implements EntityResolver { 570 Map properties; 571 Map sysProperties; 572 List sources; 573 List javadoc; 574 List installFolders; 575 String name; 576 boolean isDefault; 577 578 private Map propertyMap; 579 private StringBuffer buffer; 580 private List path; 581 582 583 public void startDocument () throws org.xml.sax.SAXException { 584 } 585 586 public void endDocument () throws org.xml.sax.SAXException { 587 } 588 589 public void startElement (String uri, String localName, String qName, org.xml.sax.Attributes attrs) 590 throws org.xml.sax.SAXException { 591 if (ELEMENT_PLATFORM.equals(qName)) { 592 name = attrs.getValue(ATTR_PLATFORM_NAME); 593 isDefault = "yes".equals(attrs.getValue(ATTR_PLATFORM_DEFAULT)); 594 } else if (ELEMENT_PROPERTIES.equals(qName)) { 595 if (properties == null) 596 properties = new HashMap(17); 597 propertyMap = properties; 598 } else if (ELEMENT_SYSPROPERTIES.equals(qName)) { 599 if (sysProperties == null) 600 sysProperties = new HashMap(17); 601 propertyMap = sysProperties; 602 } else if (ELEMENT_PROPERTY.equals(qName)) { 603 if (propertyMap == null) 604 throw new SAXException("property w/o properties or sysproperties"); 605 String name = attrs.getValue(ATTR_PROPERTY_NAME); 606 if (name == null || "".equals(name)) 607 throw new SAXException("missing name"); 608 String val = attrs.getValue(ATTR_PROPERTY_VALUE); 609 propertyMap.put(name, val); 610 } 611 else if (ELEMENT_SOURCEPATH.equals(qName)) { 612 this.sources = new ArrayList (); 613 this.path = this.sources; 614 } 615 else if (ELEMENT_JAVADOC.equals(qName)) { 616 this.javadoc = new ArrayList (); 617 this.path = this.javadoc; 618 } 619 else if (ELEMENT_JDKHOME.equals(qName)) { 620 this.installFolders = new ArrayList (); 621 this.path = this.installFolders; 622 } 623 else if (ELEMENT_RESOURCE.equals(qName)) { 624 this.buffer = new StringBuffer (); 625 } 626 } 627 628 public void endElement (String uri, String localName, String qName) throws org.xml.sax.SAXException { 629 if (ELEMENT_PROPERTIES.equals(qName) || 630 ELEMENT_SYSPROPERTIES.equals(qName)) { 631 propertyMap = null; 632 } 633 else if (ELEMENT_SOURCEPATH.equals(qName) || ELEMENT_JAVADOC.equals(qName)) { 634 path = null; 635 } 636 else if (ELEMENT_RESOURCE.equals(qName)) { 637 try { 638 this.path.add (new URL (this.buffer.toString())); 639 } catch (MalformedURLException mue) { 640 ErrorManager.getDefault().notify(mue); 641 } 642 this.buffer = null; 643 } 644 } 645 646 public void characters(char chars[], int start, int length) throws SAXException { 647 if (this.buffer != null) { 648 this.buffer.append(chars, start, length); 649 } 650 } 651 652 public org.xml.sax.InputSource resolveEntity(String publicId, String systemId) 653 throws SAXException { 654 if (PLATFORM_DTD_ID.equals (publicId)) { 655 return new org.xml.sax.InputSource (new ByteArrayInputStream (new byte[0])); 656 } else { 657 return null; } 659 } 660 661 } 662 663 } 664 | Popular Tags |