001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.mobility.cldcplatform;
043:
044: import java.beans.*;
045: import java.io.*;
046: import java.lang.ref.*;
047: import java.util.*;
048:
049: import org.openide.ErrorManager;
050: import org.openide.cookies.*;
051: import org.openide.filesystems.*;
052: import org.openide.loaders.*;
053: import org.openide.nodes.Node;
054: import org.openide.util.RequestProcessor;
055: import org.openide.util.Lookup;
056: import org.openide.util.WeakListeners;
057: import org.openide.util.lookup.*;
058: import org.openide.xml.*;
059:
060: import org.xml.sax.*;
061:
062: import org.netbeans.api.project.ProjectManager;
063: import org.netbeans.spi.project.support.ant.EditableProperties;
064: import org.netbeans.spi.project.support.ant.PropertyUtils;
065: import org.openide.nodes.AbstractNode;
066: import org.openide.nodes.Children;
067: import org.openide.util.HelpCtx;
068: import org.openide.util.Mutex;
069: import org.openide.util.MutexException;
070:
071: /**
072: * Reads and writes the standard platform format implemented by PlatformImpl2.
073: *
074: * @author Adam Sotona, Svata Dedic
075: */
076: public class PlatformConvertor implements Environment.Provider,
077: InstanceCookie.Of, PropertyChangeListener, Runnable,
078: InstanceContent.Convertor {
079:
080: private PlatformConvertor() {
081: //to avoid instantiation
082: }
083:
084: public static PlatformConvertor createProvider(
085: @SuppressWarnings("unused")
086: final FileObject reg) {
087: return new PlatformConvertor();
088: }
089:
090: public Lookup getEnvironment(final DataObject obj) {
091: return new PlatformConvertor((XMLDataObject) obj).getLookup();
092: }
093:
094: InstanceContent cookies = new InstanceContent();
095:
096: private XMLDataObject holder;
097: private Lookup lookup;
098: private RequestProcessor.Task saveTask;
099: protected Reference<J2MEPlatform> refPlatform = new WeakReference<J2MEPlatform>(
100: null);
101: final private LinkedList<PropertyChangeEvent> keepAlive = new LinkedList<PropertyChangeEvent>();
102:
103: @SuppressWarnings("unchecked")
104: private PlatformConvertor(XMLDataObject object) {
105: this .holder = object;
106: this .holder.getPrimaryFile().addFileChangeListener(
107: new FileChangeAdapter() {
108: public void fileDeleted(final FileEvent fe) {
109: try {
110: ProjectManager.mutex().writeAccess(
111: new Mutex.ExceptionAction() {
112: public Object run()
113: throws IOException {
114: final String systemName = fe
115: .getFile()
116: .getName();
117: final String propPrefix = "platforms."
118: + systemName + "."; //NOI18N
119: boolean changed = false;
120: final EditableProperties props = PropertyUtils
121: .getGlobalProperties();
122: for (final Iterator it = props
123: .keySet()
124: .iterator(); it
125: .hasNext();) {
126: final String key = (String) it
127: .next();
128: if (key
129: .startsWith(propPrefix)) {
130: it.remove();
131: changed = true;
132: }
133: }
134: if (changed) {
135: PropertyUtils
136: .putGlobalProperties(props);
137: }
138: return null;
139: }
140: });
141: } catch (MutexException e) {
142: ErrorManager.getDefault().notify(e);
143: }
144: }
145: });
146: cookies = new InstanceContent();
147: cookies.add(this );
148: lookup = new AbstractLookup(cookies);
149: cookies.add(Node.class, this );
150: }
151:
152: Lookup getLookup() {
153: return lookup;
154: }
155:
156: public Class instanceClass() {
157: return J2MEPlatform.class;
158: }
159:
160: public Object instanceCreate() throws java.io.IOException {
161: synchronized (this ) {
162: final Object o = refPlatform.get();
163: if (o != null)
164: return o;
165: final H handler = new H();
166: try {
167: final XMLReader reader = XMLUtil.createXMLReader();
168: final InputSource is = new org.xml.sax.InputSource(
169: holder.getPrimaryFile().getInputStream());
170: is.setSystemId(holder.getPrimaryFile().getPath());
171: reader.setContentHandler(handler);
172: reader.setErrorHandler(handler);
173: reader.setEntityResolver(EntityCatalog.getDefault());
174:
175: reader.parse(is);
176: } catch (SAXException ex) {
177: final Exception x = ex.getException();
178: ex.printStackTrace();
179: if (x instanceof java.io.IOException)
180: throw (IOException) x;
181: throw new java.io.IOException(ex.getMessage());
182: }
183:
184: final J2MEPlatform inst = createPlatform(handler);
185: refPlatform = new WeakReference<J2MEPlatform>(inst);
186:
187: updateBuildProperties(inst);
188: return inst;
189: }
190: }
191:
192: J2MEPlatform createPlatform(final H handler) {
193: final J2MEPlatform p = handler.platform;
194:
195: p.addPropertyChangeListener(this );
196: return p;
197: }
198:
199: public String instanceName() {
200: return holder.getName();
201: }
202:
203: @SuppressWarnings("unchecked")
204: public boolean instanceOf(final Class type) {
205: return type.isAssignableFrom(J2MEPlatform.class);
206: }
207:
208: final static int DELAY = 200;
209:
210: public void propertyChange(final PropertyChangeEvent evt) {
211: synchronized (this ) {
212: if (saveTask == null)
213: saveTask = RequestProcessor.getDefault().create(this );
214: }
215: synchronized (this ) {
216: keepAlive.add(evt);
217: }
218: saveTask.schedule(DELAY);
219: }
220:
221: public void run() {
222: PropertyChangeEvent e;
223:
224: synchronized (this ) {
225: e = keepAlive.removeFirst();
226: }
227: final J2MEPlatform plat = (J2MEPlatform) e.getSource();
228: updateBuildProperties(plat);
229: try {
230: holder.getPrimaryFile().getFileSystem().runAtomicAction(
231: new W(plat, holder));
232: } catch (java.io.IOException ex) {
233: ErrorManager.getDefault().notify(
234: ErrorManager.INFORMATIONAL, ex);
235: }
236: }
237:
238: static interface J2MEPlatformCookie extends Node.Cookie {
239: public J2MEPlatform getPlatform();
240: }
241:
242: static class J2MEPlatformNode extends AbstractNode implements
243: PropertyChangeListener {
244:
245: J2MEPlatform platform;
246:
247: J2MEPlatformNode(J2MEPlatform platform, DataObject holder) {
248: super (Children.LEAF, Lookups.fixed(new Object[] { platform,
249: holder }));
250: this .platform = platform;
251: platform.addPropertyChangeListener(WeakListeners
252: .propertyChange(this , platform));
253: setIconBaseWithExtension("org/netbeans/modules/mobility/cldcplatform/resources/platform.gif"); //NOI18N
254: }
255:
256: public String getDisplayName() {
257: return platform.getDisplayName();
258: }
259:
260: public String getHtmlDisplayName() {
261: if (platform.isValid()) {
262: return null;
263: }
264: return "<font color=\"#A40000\">"
265: + this .platform.getDisplayName() + "</font>";
266: }
267:
268: public HelpCtx getHelpCtx() {
269: return new HelpCtx(J2MEPlatformNode.class);
270: }
271:
272: public boolean hasCustomizer() {
273: return true;
274: }
275:
276: public java.awt.Component getCustomizer() {
277: if (platform.getInstallFolders().size() == 0) {
278: return new BrokenPlatformCustomizer();
279: }
280: return new CustomizerPanel(this .platform);
281: }
282:
283: public void propertyChange(@SuppressWarnings("unused")
284: final PropertyChangeEvent evt) {
285: fireDisplayNameChange(null, getDisplayName());
286: }
287: }
288:
289: public Object convert(final Object obj) {
290: if (obj == Node.class) {
291: Object p;
292:
293: try {
294: p = instanceCreate();
295: return new J2MEPlatformNode((J2MEPlatform) p, holder);
296: } catch (Exception ex) {
297: ErrorManager.getDefault().notify(ex);
298: }
299: }
300: return null;
301: }
302:
303: public String displayName(final Object obj) {
304: return ((Class) obj).getName();
305: }
306:
307: public String id(final Object obj) {
308: return obj.toString();
309: }
310:
311: public Class type(final Object obj) {
312: return (Class) obj;
313: }
314:
315: public static DataObject create(final J2MEPlatform plat,
316: final DataFolder f, final String idName) throws IOException {
317: final W w = new W(plat, f, idName);
318: f.getPrimaryFile().getFileSystem().runAtomicAction(w);
319: return w.holder;
320: }
321:
322: static class W implements FileSystem.AtomicAction {
323: J2MEPlatform instance;
324: MultiDataObject holder;
325: String name;
326: DataFolder f;
327:
328: W(J2MEPlatform instance, MultiDataObject holder) {
329: this .instance = instance;
330: this .holder = holder;
331: }
332:
333: W(J2MEPlatform instance, DataFolder f, String n) {
334: this .instance = instance;
335: this .name = n;
336: this .f = f;
337: }
338:
339: public void run() throws java.io.IOException {
340: FileLock lck;
341: FileObject data;
342:
343: if (holder != null) {
344: data = holder.getPrimaryEntry().getFile();
345: lck = holder.getPrimaryEntry().takeLock();
346: } else {
347: final FileObject folder = f.getPrimaryFile();
348: final String fn = FileUtil.findFreeFileName(folder,
349: name, "xml"); //NOI18N
350: instance.setName(fn);
351: data = folder.createData(fn, "xml"); //NOI18N
352: lck = data.lock();
353: }
354: try {
355: final OutputStream ostm = data.getOutputStream(lck);
356: final PrintWriter writer = new PrintWriter(
357: new OutputStreamWriter(ostm, "UTF8")); //NOI18N
358: write(writer);
359: writer.flush();
360: writer.close();
361: ostm.close();
362: } finally {
363: lck.releaseLock();
364: }
365: if (holder == null) {
366: holder = (MultiDataObject) DataObject.find(data);
367: }
368: }
369:
370: void write(final PrintWriter pw) throws IOException {
371: pw.println("<?xml version='1.0'?>"); //NOI18N
372: pw
373: .println("<!DOCTYPE platform PUBLIC '-//NetBeans//DTD J2ME PlatformDefinition 1.0//EN' 'http://www.netbeans.org/dtds/j2me-platformdefinition-1_0.dtd'>"); //NOI18N
374: pw.print("<platform name=\""
375: + XMLUtil.toAttributeValue(instance.getName()) //NOI18N
376: + "\" home=\""
377: + XMLUtil.toAttributeValue(instance.getHomePath()) //NOI18N
378: + "\" type=\""
379: + XMLUtil.toAttributeValue(instance.getType()) //NOI18N
380: + "\" displayname=\""
381: + XMLUtil.toAttributeValue(instance
382: .getDisplayName()) //NOI18N
383: + "\" srcpath=\""
384: + XMLUtil
385: .toAttributeValue(instance.getSourcePath()) //NOI18N
386: + "\" docpath=\""
387: + XMLUtil.toAttributeValue(instance
388: .getJavadocPath())); //NOI18N
389: if (instance.getPreverifyCmd() != null)
390: pw.print("\" preverifycmd=\""
391: + XMLUtil.toAttributeValue(instance
392: .getPreverifyCmd())); //NOI18N
393: if (instance.getRunCmd() != null)
394: pw
395: .print("\" runcmd=\""
396: + XMLUtil.toAttributeValue(instance
397: .getRunCmd())); //NOI18N
398: if (instance.getDebugCmd() != null)
399: pw.print("\" debugcmd=\""
400: + XMLUtil.toAttributeValue(instance
401: .getDebugCmd())); //NOI18N
402: pw.println("\">"); //NOI18N
403: final J2MEPlatform.Device[] devices = instance.getDevices();
404: for (int i = 0; i < devices.length; i++) {
405: final J2MEPlatform.Device d = devices[i];
406: pw.print(" <device name=\""
407: + XMLUtil.toAttributeValue(d.getName())); //NOI18N
408: final String securitydomains = PlatformConvertor
409: .array2string(d.getSecurityDomains());
410: if (securitydomains != null)
411: pw
412: .print("\" securitydomains=\""
413: + XMLUtil
414: .toAttributeValue(securitydomains)); //NOI18N
415: if (d.getDescription() != null)
416: pw.print("\" description=\""
417: + XMLUtil.toAttributeValue(d
418: .getDescription())); //NOI18N
419: pw.println("\">"); //NOI18N
420: final J2MEPlatform.J2MEProfile[] profiles = d
421: .getProfiles();
422: for (int j = 0; j < profiles.length; j++) {
423: final J2MEPlatform.J2MEProfile p = profiles[j];
424: pw
425: .print(" <"
426: + p.getType() //NOI18N
427: + " name=\""
428: + XMLUtil.toAttributeValue(p
429: .getName()) //NOI18N
430: + "\" version=\""
431: + XMLUtil.toAttributeValue(p
432: .getVersion().toString()) //NOI18N
433: + "\" displayname=\""
434: + XMLUtil.toAttributeValue(p
435: .getDisplayName()) //NOI18N
436: + "\" classpath=\""
437: + XMLUtil.toAttributeValue(p
438: .getClassPath())); //NOI18N
439: if (p.getDependencies() != null)
440: pw.print("\" dependencies=\""
441: + XMLUtil.toAttributeValue(p
442: .getDependencies())); //NOI18N
443: pw.println("\" default=\""
444: + Boolean.toString(p.isDefault()) + "\"/>"); //NOI18N
445: }
446: final J2MEPlatform.Screen s = d.getScreen();
447: if (s != null) {
448: final Integer sw = s.getWidth();
449: final Integer sh = s.getHeight();
450: final Integer sd = s.getBitDepth();
451: final Boolean sc = s.getColor();
452: final Boolean st = s.getTouch();
453: if (sw != null || sh != null || sd != null
454: || sc != null || st != null) {
455: pw.print(" <screen"); //NOI18N
456: if (sw != null)
457: pw.print(" width=\"" + sw + "\""); //NOI18N
458: if (sh != null)
459: pw.print(" height=\"" + sh + "\""); //NOI18N
460: if (sd != null)
461: pw.print(" bitDepth=\"" + sd + "\""); //NOI18N
462: if (sc != null)
463: pw.print(" isColor=\"" + sc + "\""); //NOI18N
464: if (st != null)
465: pw.print(" isTouch=\"" + st + "\""); //NOI18N
466: pw.println("/>"); //NOI18N
467: }
468: }
469: pw.println(" </device>"); //NOI18N
470: }
471: pw.println("</platform>"); //NOI18N
472: }
473:
474: void writeProperties(final Map<String, String> props,
475: final PrintWriter pw) throws IOException {
476: final Collection<String> sortedProps = new TreeSet<String>(
477: props.keySet());
478: for (final String n : sortedProps) { //= (String)it.next();
479: final String val = props.get(n);
480: pw.println(" <property name='" + //NOI18N
481: XMLUtil.toAttributeValue(n) + "' value='" + //NOI18N
482: XMLUtil.toAttributeValue(val) + "'/>"); //NOI18N
483: }
484: }
485: }
486:
487: static final String ELEMENT_PLATFORM = "platform"; // NOI18N
488: static final String ELEMENT_DEVICE = "device"; // NOI18N
489: static final String ELEMENT_CONFIGURATION = "configuration"; // NOI18N
490: static final String ELEMENT_PROFILE = "profile"; // NOI18N
491: static final String ELEMENT_OPTIONAL = "optional"; // NOI18N
492: static final String ELEMENT_SCREEN = "screen"; // NOI18N
493: static final String ATTR_PROPERTY_NAME = "name"; // NOI18N
494: static final String ATTR_PROPERTY_HOME = "home"; // NOI18N
495: static final String ATTR_PROPERTY_TYPE = "type"; // NOI18N
496: static final String ATTR_PROPERTY_DISPLAYNAME = "displayname"; // NOI18N
497: static final String ATTR_PROPERTY_SRCPATH = "srcpath"; // NOI18N
498: static final String ATTR_PROPERTY_DOCPATH = "docpath"; // NOI18N
499: static final String ATTR_PROPERTY_DESCRIPTION = "description"; // NOI18N
500: static final String ATTR_PROPERTY_SECURITY_DOMAINS = "securitydomains"; // NOI18N
501: static final String ATTR_PROPERTY_PREVERIFYCMD = "preverifycmd"; // NOI18N
502: static final String ATTR_PROPERTY_RUNCMD = "runcmd"; // NOI18N
503: static final String ATTR_PROPERTY_DEBUGCMD = "debugcmd"; // NOI18N
504: static final String ATTR_PROPERTY_VERSION = "version"; // NOI18N
505: static final String ATTR_PROPERTY_DEPENDENCIES = "dependencies"; // NOI18N
506: static final String ATTR_PROPERTY_CLASSPATH = "classpath"; // NOI18N
507: static final String ATTR_PROPERTY_DEFAULT = "default"; // NOI18N
508: static final String ATTR_SCREEN_WIDTH = "width"; // NOI18N
509: static final String ATTR_SCREEN_HEIGHT = "height"; // NOI18N
510: static final String ATTR_SCREEN_BITDEPTH = "bitDepth"; // NOI18N
511: static final String ATTR_SCREEN_ISCOLOR = "isColor"; // NOI18N
512: static final String ATTR_SCREEN_ISTOUCH = "isTouch"; // NOI18N
513:
514: static class H extends org.xml.sax.helpers.DefaultHandler {
515:
516: J2MEPlatform platform;
517:
518: private String name;
519: private String home;
520: private String type;
521: private String displayName;
522: private String srcPath;
523: private String docPath;
524:
525: private ArrayList<J2MEPlatform.Device> devices;
526: private String devName;
527: private String devDesc;
528: private String[] devSecurityDomains;
529: private String devPrevCmd;
530: private String devRunCmd;
531: private String devDebugCmd;
532: private ArrayList<J2MEPlatform.J2MEProfile> profiles;
533:
534: private J2MEPlatform.Screen screen;
535:
536: public J2MEPlatform.Device[] getDevices() {
537: return devices.toArray(new J2MEPlatform.Device[devices
538: .size()]);
539: }
540:
541: @SuppressWarnings("unused")
542: public void startDocument() throws org.xml.sax.SAXException {
543: }
544:
545: @SuppressWarnings("unused")
546: public void endDocument() throws org.xml.sax.SAXException {
547: }
548:
549: private String getMandatoryValue(
550: final org.xml.sax.Attributes attrs, final String name)
551: throws SAXException {
552: final String val = attrs.getValue(name);
553: if (val == null || val.length() < 1)
554: throw new SAXException("Missing " + name); //NOI18N
555: return val;
556: }
557:
558: public void startElement(@SuppressWarnings("unused")
559: final String uri, @SuppressWarnings("unused")
560: final String localName, final String qName,
561: final org.xml.sax.Attributes attrs) throws SAXException {
562: if (ELEMENT_PLATFORM.equals(qName)) {
563: if (platform != null || devices != null)
564: throw new SAXException("Invalid start of element "
565: + ELEMENT_PLATFORM); //NOI18N
566: name = getMandatoryValue(attrs, ATTR_PROPERTY_NAME);
567: home = getMandatoryValue(attrs, ATTR_PROPERTY_HOME);
568: type = getMandatoryValue(attrs, ATTR_PROPERTY_TYPE);
569: displayName = attrs.getValue(ATTR_PROPERTY_DISPLAYNAME);
570: srcPath = attrs.getValue(ATTR_PROPERTY_SRCPATH);
571: docPath = attrs.getValue(ATTR_PROPERTY_DOCPATH);
572: devPrevCmd = attrs.getValue(ATTR_PROPERTY_PREVERIFYCMD);
573: devRunCmd = attrs.getValue(ATTR_PROPERTY_RUNCMD);
574: devDebugCmd = attrs.getValue(ATTR_PROPERTY_DEBUGCMD);
575: } else if (ELEMENT_DEVICE.equals(qName)) {
576: if (profiles != null)
577: throw new SAXException("Invalid start of element "
578: + ELEMENT_DEVICE); //NOI18N
579: devName = getMandatoryValue(attrs, ATTR_PROPERTY_NAME);
580: devDesc = attrs.getValue(ATTR_PROPERTY_DESCRIPTION);
581: devSecurityDomains = PlatformConvertor
582: .string2array(attrs
583: .getValue(ATTR_PROPERTY_SECURITY_DOMAINS));
584: profiles = new ArrayList<J2MEPlatform.J2MEProfile>();
585: screen = null;
586: } else if (ELEMENT_CONFIGURATION.equals(qName)
587: || ELEMENT_PROFILE.equals(qName)
588: || ELEMENT_OPTIONAL.equals(qName)) {
589: final String pname = getMandatoryValue(attrs,
590: ATTR_PROPERTY_NAME);
591: final String pversion = getMandatoryValue(attrs,
592: ATTR_PROPERTY_VERSION);
593: final String pdependencies = attrs
594: .getValue(ATTR_PROPERTY_DEPENDENCIES);
595: final String pdisplayname = attrs
596: .getValue(ATTR_PROPERTY_DISPLAYNAME);
597: final String pclasspath = attrs
598: .getValue(ATTR_PROPERTY_CLASSPATH);
599: final boolean pdefault = Boolean.valueOf(
600: attrs.getValue(ATTR_PROPERTY_DEFAULT))
601: .booleanValue();
602: profiles.add(new J2MEPlatform.J2MEProfile(pname,
603: pversion, pdisplayname, qName, pdependencies,
604: pclasspath, pdefault));
605: } else if (ELEMENT_SCREEN.equals(qName)) {
606: screen = new J2MEPlatform.Screen(attrs
607: .getValue(ATTR_SCREEN_WIDTH), attrs
608: .getValue(ATTR_SCREEN_HEIGHT), attrs
609: .getValue(ATTR_SCREEN_BITDEPTH), attrs
610: .getValue(ATTR_SCREEN_ISCOLOR), attrs
611: .getValue(ATTR_SCREEN_ISTOUCH));
612: }
613: }
614:
615: public void endElement(@SuppressWarnings("unused")
616: final String uri, @SuppressWarnings("unused")
617: final String localName, final String qName)
618: throws org.xml.sax.SAXException {
619: if (ELEMENT_PLATFORM.equals(qName)) {
620: if (platform != null)
621: throw new SAXException("Invalid end of element "
622: + ELEMENT_PLATFORM); //NOI18N
623: if (devices == null)
624: throw new SAXException("Missing " + ELEMENT_DEVICE); //NOI18N
625: platform = new J2MEPlatform(name, home, type,
626: displayName, srcPath, docPath, devPrevCmd,
627: devRunCmd, devDebugCmd,
628: devices.toArray(new J2MEPlatform.Device[devices
629: .size()]));
630: } else if (ELEMENT_DEVICE.equals(qName)) {
631: if (devices == null)
632: devices = new ArrayList<J2MEPlatform.Device>();
633: devices
634: .add(new J2MEPlatform.Device(
635: devName,
636: devDesc,
637: devSecurityDomains,
638: profiles
639: .toArray(new J2MEPlatform.J2MEProfile[profiles
640: .size()]), screen));
641: profiles = null;
642: }
643: }
644: }
645:
646: private static void updateBuildProperties(final J2MEPlatform p) {
647: final String name = p.getName();
648: RequestProcessor.getDefault().post(new Runnable() {
649: public void run() {
650: try {
651: ProjectManager.mutex().writeAccess(
652: new Mutex.ExceptionAction() {
653: public Object run() throws Exception {
654: final EditableProperties props = PropertyUtils
655: .getGlobalProperties();
656: final Iterator it = props
657: .entrySet().iterator();
658: final String prefix = createName(
659: name, "");//NOI18N
660: while (it.hasNext()) {
661: if (((String) ((Map.Entry) it
662: .next()).getKey())
663: .startsWith(prefix))
664: it.remove();
665: }
666: props.setProperty(createName(name,
667: "home"), p.getHomePath()); //NOI18N
668: props.setProperty(createName(name,
669: "type"), p.getType()); //NOI18N
670: props
671: .setProperty(
672: createName(name,
673: "preverifycommandline"),
674: p.getPreverifyCmd() != null ? p
675: .getPreverifyCmd()
676: : ""); // NOI18N
677: props.setProperty(createName(name,
678: "runcommandline"), p
679: .getRunCmd() != null ? p
680: .getRunCmd() : ""); // NOI18N
681: props.setProperty(createName(name,
682: "debugcommandline"), p
683: .getDebugCmd() != null ? p
684: .getDebugCmd() : ""); // NOI18N
685: PropertyUtils
686: .putGlobalProperties(props);
687: return null;
688: }
689: });
690: } catch (MutexException me) {
691: ErrorManager.getDefault().notify(me.getException());
692: }
693: }
694: });
695: }
696:
697: protected static String createName(final String propName,
698: final String propType) {
699: return "platforms." + propName + "." + propType; //NOI18N
700: }
701:
702: public static String array2string(final String[] array) {
703: if (array == null)
704: return null;
705: StringBuffer sb = null;
706: for (int a = 0; a < array.length; a++) {
707: if (sb == null)
708: sb = new StringBuffer(array[a].length() * array.length);
709: else
710: sb.append(',');
711: sb.append(array[a]);
712: }
713: return (sb != null) ? sb.toString() : ""; //NOI18N
714: }
715:
716: public static String[] string2array(final String string) {
717: if (string == null)
718: return null;
719: final ArrayList<String> list = new ArrayList<String>();
720: final StringTokenizer st = new StringTokenizer(string, ","); //NOI18N
721: while (st.hasMoreTokens())
722: list.add(st.nextToken().trim());
723: return list.toArray(new String[list.size()]);
724: }
725:
726: protected static String toJavaIdentifier(final String s) {
727: final StringBuffer sb = new StringBuffer();
728: for (int i = 0; i < s.length(); i++) {
729: final char ch = s.charAt(i);
730: if (sb.length() == 0 && Character.isJavaIdentifierStart(ch))
731: sb.append(ch);
732: else if (Character.isJavaIdentifierPart(ch))
733: sb.append(ch);
734: }
735: return sb.toString();
736: }
737:
738: private static final String EMPTY = ""; //NOI18N
739:
740: public static Map<String, String> extractPlatformProperties(
741: final String prefix, final J2MEPlatform platform,
742: J2MEPlatform.Device device, final String reqConfiguration,
743: final String reqProfile) {
744: final HashMap<String, String> props = new HashMap();
745: String pname, pdesc, dname, type;
746: J2MEPlatform.J2MEProfile configuration = null, profile = null;
747: final StringBuffer apis = new StringBuffer(), classpath = new StringBuffer();
748: final HashMap<String, String> abilities = new HashMap<String, String>();
749: if (platform == null) {
750: pname = ".default"; //NOI18N
751: pdesc = EMPTY;
752: dname = EMPTY;
753: type = EMPTY;
754: } else {
755: pname = platform.getName();
756: pdesc = platform.getDisplayName();
757: type = platform.getType();
758: if (device == null && platform.getDevices() != null
759: && platform.getDevices().length > 0)
760: device = platform.getDevices()[0];
761: if (device == null) {
762: dname = EMPTY;
763: } else {
764: dname = device.getName();
765: final J2MEPlatform.J2MEProfile profs[] = device
766: .getProfiles();
767: for (int i = 0; i < profs.length; i++) {
768: if (J2MEPlatform.J2MEProfile.TYPE_CONFIGURATION
769: .equals(profs[i].getType())) {
770: if (configuration == null //this code select by priority: 1.requested 2.default 3.any configuration
771: || (!configuration.toString().equals(
772: reqConfiguration) && profs[i]
773: .isDefault())
774: || (profs[i].toString()
775: .equals(reqConfiguration)))
776: configuration = profs[i];
777: } else if (J2MEPlatform.J2MEProfile.TYPE_PROFILE
778: .equals(profs[i].getType())) {
779: if (profile == null //this code select by priority: 1.requested 2.default 3.any profile
780: || (!profile.toString().equals(
781: reqProfile) && profs[i]
782: .isDefault())
783: || (profs[i].toString()
784: .equals(reqProfile)))
785: profile = profs[i];
786: } else if (profs[i].isDefault()) {
787: if (apis.length() > 0)
788: apis.append(',');
789: apis.append(profs[i].toString());
790:
791: if (classpath.length() > 0)
792: classpath.append(':');
793: classpath.append(profs[i].getClassPath());
794: }
795: final String version = profs[i].getVersion() == null ? null
796: : profs[i].getVersion().toString();
797: final String ability = toValidAbility(profs[i]
798: .getName());
799: if (ability != null) {
800: final String val = abilities.get(ability);
801: if (val == null
802: || (version != null && version
803: .compareTo(val) > 0))
804: abilities.put(ability, version);
805: }
806: }
807: if (configuration != null) {
808: if (classpath.length() > 0)
809: classpath.append(':');
810: classpath.append(configuration.getClassPath());
811: }
812: if (profile != null) {
813: if (classpath.length() > 0)
814: classpath.append(':');
815: classpath.append(profile.getClassPath());
816: }
817: final J2MEPlatform.Screen scr = device.getScreen();
818: if (scr != null) {
819: if (scr.getColor() != null
820: && scr.getColor().booleanValue())
821: abilities.put("ColorScreen", null); //NOI18N
822: if (scr.getTouch() != null
823: && scr.getTouch().booleanValue())
824: abilities.put("TouchScreen", null); //NOI18N
825: if (scr.getBitDepth() != null)
826: abilities.put("ScreenColorDepth", scr
827: .getBitDepth().toString()); //NOI18N
828: if (scr.getWidth() != null)
829: abilities.put("ScreenWidth", scr.getWidth()
830: .toString()); //NOI18N
831: if (scr.getHeight() != null)
832: abilities.put("ScreenHeight", scr.getHeight()
833: .toString()); //NOI18N
834: }
835: }
836: }
837: props.put(prefix + "platform.active", pname); //NOI18N
838: props.put(prefix + "platform.active.description", pdesc); //NOI18N
839: props.put(prefix + "platform.device", dname); //NOI18N
840: props.put(prefix + "platform.configuration",
841: configuration == null ? "CLDC-1.0" : configuration
842: .toString()); //NOI18N
843: props.put(prefix + "platform.profile",
844: profile == null ? "MIDP-1.0" : profile.toString()); //NOI18N
845: props.put(prefix + "platform.apis", apis.toString()); //NOI18N
846: props.put(prefix + "platform.bootclasspath",
847: device == null ? classpath.toString() : device
848: .sortClasspath(classpath.toString())); //NOI18N
849: props.put(prefix + "abilities", encodeAbilities(abilities)); //NOI18N
850: props.put(prefix + "platform.type", type); //NOI18N
851: props.put(prefix + "platform.trigger", "CLDC"); //NOI18N
852: return props;
853: }
854:
855: private static String toValidAbility(final String s) {
856: final StringBuffer sb = new StringBuffer();
857: for (int i = 0; i < s.length(); i++) {
858: final char c = s.charAt(i);
859: if (Character.isJavaIdentifierPart(c) || c == '.'
860: || c == '/' || c == '\\')
861: sb.append(c);
862: }
863: if (sb.length() == 0)
864: return null;
865: if (!Character.isJavaIdentifierStart(sb.charAt(0)))
866: sb.insert(0, '_');
867: return sb.toString();
868: }
869:
870: private static String encodeAbilities(
871: final Map<String, String> value) {
872: final StringBuffer sb = new StringBuffer();
873: for (final Map.Entry<String, String> e : value.entrySet()) {
874: sb.append(e.getKey());
875: if (e.getValue() != null && (e.getValue()).length() > 0)
876: sb.append('=').append(e.getValue());
877: sb.append(',');
878: }
879: return sb.toString();
880: }
881:
882: }
|