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: *
007: * The contents of this file are subject to the terms of either the GNU
008: * General Public License Version 2 only ("GPL") or the Common
009: * Development and Distribution License("CDDL") (collectively, the
010: * "License"). You may not use this file except in compliance with the
011: * License. You can obtain a copy of the License at
012: * http://www.netbeans.org/cddl-gplv2.html
013: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
014: * specific language governing permissions and limitations under the
015: * License. When distributing the software, include this License Header
016: * Notice in each file and include the License file at
017: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
018: * particular file as subject to the "Classpath" exception as provided
019: * by Sun in the GPL Version 2 section of the License file that
020: * accompanied this code. If applicable, add the following below the
021: * License Header, with the fields enclosed by brackets [] replaced by
022: * your own identifying information:
023: * "Portions Copyrighted [year] [name of copyright owner]"
024: *
025: * Contributor(s):
026: *
027: * The Original Software is NetBeans. The Initial Developer of the Original
028: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
029: * Microsystems, Inc. All Rights Reserved.
030: *
031: * If you wish your version of this file to be governed by only the CDDL
032: * or only the GPL Version 2, indicate your decision by adding
033: * "[Contributor] elects to include this software in this distribution
034: * under the [CDDL or GPL Version 2] license." If you do not indicate a
035: * single choice of license, a recipient has the option to distribute
036: * your version of this file under either the CDDL, the GPL Version 2 or
037: * to extend the choice of license to its licensees as provided above.
038: * However, if you add GPL Version 2 code and therefore, elected the GPL
039: * Version 2 license, then the option applies only if the new code is
040: * made subject to such option by the copyright holder.
041: */
042:
043: package org.netbeans.modules.j2me.cdc.project.ricoh;
044:
045: import java.awt.Component;
046: import java.io.File;
047: import java.io.FileNotFoundException;
048: import java.io.IOException;
049: import java.io.InputStream;
050: import java.io.OutputStream;
051: import java.io.PrintWriter;
052: import java.text.MessageFormat;
053: import java.util.ArrayList;
054: import java.util.HashSet;
055: import java.util.Iterator;
056: import java.util.LinkedHashSet;
057: import java.util.List;
058: import java.util.Map;
059: import java.util.NoSuchElementException;
060: import java.util.Properties;
061: import java.util.Set;
062: import java.util.StringTokenizer;
063: import java.util.zip.ZipEntry;
064: import java.util.zip.ZipInputStream;
065:
066: import javax.swing.JComponent;
067: import javax.swing.event.ChangeListener;
068: import javax.xml.parsers.ParserConfigurationException;
069:
070: import org.netbeans.api.java.platform.JavaPlatform;
071: import org.netbeans.api.java.platform.JavaPlatformManager;
072: import org.netbeans.api.java.platform.Specification;
073: import org.netbeans.api.project.Project;
074: import org.netbeans.api.project.ProjectManager;
075: import org.netbeans.modules.j2me.cdc.platform.CDCPlatform;
076: import org.netbeans.modules.j2me.cdc.project.CDCPropertiesDescriptor;
077: import org.netbeans.modules.j2me.cdc.project.ricoh.dalp.DalpParser;
078: import org.netbeans.modules.j2me.cdc.project.ricoh.dalp.DalpParserHandlerImpl;
079: import org.netbeans.modules.j2me.cdc.project.ui.wizards.NewCDCProjectWizardIterator;
080: import org.netbeans.modules.j2me.cdc.project.ui.wizards.PanelConfigurePlatform;
081: import org.netbeans.modules.j2me.cdc.project.ui.wizards.PanelConfigureProject;
082: import org.netbeans.modules.mobility.project.DefaultPropertiesDescriptor;
083: import org.netbeans.modules.mobility.project.ui.wizard.PlatformSelectionPanel;
084: import org.netbeans.modules.mobility.project.J2MEProjectGenerator;
085: import org.netbeans.modules.mobility.project.ui.wizard.PlatformInstallPanel;
086: import org.netbeans.spi.project.ui.templates.support.Templates;
087: import org.netbeans.spi.project.support.ant.AntProjectHelper;
088: import org.netbeans.spi.project.support.ant.EditableProperties;
089: import org.netbeans.spi.project.support.ant.ReferenceHelper;
090: import org.netbeans.spi.project.ui.support.ProjectChooser;
091: import org.openide.ErrorManager;
092: import org.openide.WizardDescriptor;
093: import org.openide.filesystems.FileLock;
094: import org.openide.filesystems.FileObject;
095: import org.openide.filesystems.FileUtil;
096: import org.openide.util.Mutex;
097: import org.openide.util.MutexException;
098: import org.openide.util.NbBundle;
099: import org.xml.sax.InputSource;
100: import org.xml.sax.SAXException;
101:
102: public class SamplesWizardIterator implements
103: WizardDescriptor.InstantiatingIterator {
104:
105: static final String PROP_NAME_INDEX = "nameIndex"; //NOI18N
106:
107: private static final String MANIFEST_FILE = "manifest.mf"; // NOI18N
108:
109: private static final long serialVersionUID = 1L;
110:
111: private int type = NewCDCProjectWizardIterator.TYPE_SAMPLE;
112:
113: private int index;
114: private WizardDescriptor.Panel[] panels;
115: private WizardDescriptor wiz;
116: private String platform;
117: private String preferredName;
118:
119: public SamplesWizardIterator() {
120: }
121:
122: public static SamplesWizardIterator createIterator() {
123: return new SamplesWizardIterator();
124: }
125:
126: private WizardDescriptor.Panel[] createPanels() {
127: int i = getNumberOfSuitableCdcPlatforms(platform);
128: return i != 0 ? new WizardDescriptor.Panel[] {
129: new PanelConfigurePlatform(platform),
130: new PanelConfigureProject(this .type, preferredName) }
131: : new WizardDescriptor.Panel[] {
132: new PlatformInstallPanel.WizardPanel(platform,
133: CDCPlatform.PLATFORM_CDC),
134: new PanelConfigurePlatform(platform),
135: new PanelConfigureProject(this .type,
136: preferredName) };
137: }
138:
139: private String[] createSteps() {
140: int i = getNumberOfSuitableCdcPlatforms(platform);
141: return i != 0 ? new String[] {
142: NbBundle.getMessage(NewCDCProjectWizardIterator.class,
143: "LAB_SelectPlatform"),
144: NbBundle.getMessage(NewCDCProjectWizardIterator.class,
145: "LAB_ConfigureProject") } : new String[] {
146: NbBundle.getMessage(NewCDCProjectWizardIterator.class,
147: "LAB_Step_AddPlatform"), //NOI18N
148: NbBundle.getMessage(NewCDCProjectWizardIterator.class,
149: "LAB_SelectPlatform"),
150: NbBundle.getMessage(NewCDCProjectWizardIterator.class,
151: "LAB_ConfigureProject") };
152: }
153:
154: private Properties parseRicohAdditionalResources(
155: FileObject projectDir) {
156: FileObject[] fos = projectDir.getChildren();
157: for (int i = 0; i < fos.length; i++) {
158: FileObject dalp = fos[i];
159: if ("dalp".compareToIgnoreCase(dalp.getExt()) == 0) {
160: Properties properties = new Properties();
161: DalpParserHandlerImpl handler = new DalpParserHandlerImpl(
162: projectDir, properties);
163: try {
164: DalpParser.parse(new InputSource(dalp
165: .getInputStream()), handler);
166: } catch (FileNotFoundException ex) {
167: ErrorManager.getDefault().notify(ex);
168: } catch (IOException ex) {
169: ErrorManager.getDefault().notify(ex);
170: } catch (SAXException ex) {
171: ErrorManager.getDefault().notify(ex);
172: } catch (ParserConfigurationException ex) {
173: ErrorManager.getDefault().notify(ex);
174: }
175: return properties;
176: }
177: }
178: return null;
179: }
180:
181: public Set/*<FileObject>*/instantiate() throws IOException {
182:
183: Set<FileObject> resultSet = new LinkedHashSet<FileObject>();
184: File dirPr = (File) wiz.getProperty("projdir"); //NOI18N
185: if (dirPr != null) {
186: dirPr = FileUtil.normalizeFile(dirPr);
187: }
188:
189: String name = (String) wiz.getProperty("name"); //NOI18N
190:
191: final String activePlatform = (String) wiz
192: .getProperty("activePlatform"); //NOI18N
193: final String activeDevice = (String) wiz
194: .getProperty("activeDevice"); //NOI18N
195: final String activeProfile = (String) wiz
196: .getProperty("activeProfile"); //NOI18N
197: Properties props = (Properties) wiz
198: .getProperty("additionalProperties"); //NOI18N
199: final FileObject template = Templates.getTemplate(wiz);
200: PlatformSelectionPanel.PlatformDescription pd = (PlatformSelectionPanel.PlatformDescription) wiz
201: .getProperty(PlatformSelectionPanel.PLATFORM_DESCRIPTION);
202: AntProjectHelper h = J2MEProjectGenerator.createProject(dirPr,
203: name, pd,
204: new J2MEProjectGenerator.ProjectGeneratorCallback() {
205: public void doPostGeneration(Project p,
206: final AntProjectHelper h, FileObject dir,
207: File projectLocationFile,
208: ArrayList<String> configurations)
209: throws IOException {
210:
211: createManifest(dir, MANIFEST_FILE);
212: unZipFile(template.getInputStream(), dir);
213:
214: final FileObject lib = dir.getFileObject("lib");
215: if (lib != null) {
216: final ReferenceHelper refHelper = (ReferenceHelper) p
217: .getLookup().lookup(
218: ReferenceHelper.class);
219: try {
220: ProjectManager.mutex().writeAccess(
221: new Mutex.ExceptionAction() {
222: public Object run()
223: throws Exception {
224: final List<String> entries = new ArrayList<String>();
225: final FileObject[] libs = lib
226: .getChildren();
227: for (int i = 0; i < libs.length; i++) {
228: String ref = refHelper
229: .createForeignFileReference(
230: FileUtil
231: .normalizeFile(FileUtil
232: .toFile(libs[i])),
233: null);
234: entries
235: .add(ref
236: + ((i < libs.length - 1) ? ";"
237: : ""));
238: }
239:
240: EditableProperties editableProps = h
241: .getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
242: editableProps
243: .setProperty(
244: "extra.classpath",
245: entries
246: .toArray(new String[entries
247: .size()]));
248: editableProps
249: .setProperty(
250: "libs.classpath",
251: entries
252: .toArray(new String[entries
253: .size()]));
254: h
255: .putProperties(
256: AntProjectHelper.PROJECT_PROPERTIES_PATH,
257: editableProps); // #47609
258: return null;
259: }
260: });
261: } catch (MutexException me) {
262: ErrorManager.getDefault().notify(me);
263: }
264: }
265:
266: final FileObject res = dir
267: .getFileObject("resources");
268: if (res != null) {
269: final ReferenceHelper refHelper = (ReferenceHelper) p
270: .getLookup().lookup(
271: ReferenceHelper.class);
272: try {
273: ProjectManager.mutex().writeAccess(
274: new Mutex.ExceptionAction() {
275: public Object run()
276: throws Exception {
277: String ref = ";"
278: + refHelper
279: .createForeignFileReference(
280: FileUtil
281: .normalizeFile(FileUtil
282: .toFile(res)),
283: null);
284:
285: EditableProperties editableProps = h
286: .getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
287: editableProps
288: .setProperty(
289: "libs.classpath",
290: editableProps
291: .getProperty("libs.classpath")
292: + ref);
293: h
294: .putProperties(
295: AntProjectHelper.PROJECT_PROPERTIES_PATH,
296: editableProps); // #47609
297: return null;
298: }
299: });
300: } catch (MutexException me) {
301: ErrorManager.getDefault().notify(me);
302: }
303: }
304:
305: Properties parsed = parseRicohAdditionalResources(dir);
306: if (parsed != null) {
307: Iterator entries = parsed.entrySet()
308: .iterator();
309: while (entries.hasNext()) {
310: final Map.Entry elem = (Map.Entry) entries
311: .next();
312: final Object value = elem.getValue();
313: if (value instanceof File) {
314: final ReferenceHelper refHelper = (ReferenceHelper) p
315: .getLookup()
316: .lookup(
317: ReferenceHelper.class);
318: if (value != null
319: && ((File) value).exists()) {
320: try {
321: ProjectManager
322: .mutex()
323: .writeAccess(
324: new Mutex.ExceptionAction() {
325: public Object run()
326: throws Exception {
327: String ref = refHelper
328: .createForeignFileReference(
329: FileUtil
330: .normalizeFile((File) value),
331: null);
332: EditableProperties props = h
333: .getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
334: props
335: .put(
336: (String) elem
337: .getKey(),
338: ref);
339: h
340: .putProperties(
341: AntProjectHelper.PROJECT_PROPERTIES_PATH,
342: props); // #47609
343: return null;
344: }
345: });
346: } catch (MutexException me) {
347: ErrorManager.getDefault()
348: .notify(me);
349: }
350: }
351: } else {
352: EditableProperties editableProps = h
353: .getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
354: editableProps.setProperty(
355: (String) elem.getKey(),
356: String.valueOf(elem
357: .getValue()));
358: h
359: .putProperties(
360: AntProjectHelper.PROJECT_PROPERTIES_PATH,
361: editableProps); // #47609
362: }
363: }
364: }
365:
366: JavaPlatform[] platforms = JavaPlatformManager
367: .getDefault()
368: .getPlatforms(
369: activePlatform,
370: new Specification(
371: CDCPlatform.PLATFORM_CDC,
372: null)); //NOI18N
373: if (platforms.length != 0) {
374: CDCPlatform cdcplatform = (CDCPlatform) platforms[0];
375: final EditableProperties ep = h
376: .getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
377: ep
378: .setProperty(
379: CDCPropertiesDescriptor.APPLICATION_NAME,
380: p.getProjectDirectory()
381: .getNameExt());
382: ep
383: .setProperty(
384: DefaultPropertiesDescriptor.PLATFORM_ACTIVE,
385: cdcplatform.getAntName()); // NOI18N
386: ep
387: .setProperty(
388: DefaultPropertiesDescriptor.PLATFORM_ACTIVE_DESCRIPTION,
389: cdcplatform
390: .getDisplayName()); // NOI18N
391: ep
392: .setProperty(
393: DefaultPropertiesDescriptor.PLATFORM_TRIGGER,
394: "CDC"); // NOI18N
395: ep
396: .setProperty(
397: DefaultPropertiesDescriptor.PLATFORM_TYPE,
398: cdcplatform.getType()); // NOI18N
399: String classVersion = cdcplatform
400: .getClassVersion();
401: ep
402: .setProperty(
403: DefaultPropertiesDescriptor.PLATFORM_DEVICE,
404: activeDevice); // NOI18N
405: ep
406: .setProperty(
407: DefaultPropertiesDescriptor.PLATFORM_PROFILE,
408: activeProfile); // NOI18N
409: //add bootclasspath
410: NewCDCProjectWizardIterator
411: .generatePlatformProperties(
412: cdcplatform, activeDevice,
413: activeProfile, ep); // NOI18N
414: ep
415: .setProperty(
416: DefaultPropertiesDescriptor.JAVAC_SOURCE,
417: classVersion != null ? classVersion
418: : "1.2"); // NOI18N
419: ep
420: .setProperty(
421: DefaultPropertiesDescriptor.JAVAC_TARGET,
422: classVersion != null ? classVersion
423: : "1.2"); // NOI18N
424: h
425: .putProperties(
426: AntProjectHelper.PROJECT_PROPERTIES_PATH,
427: ep);
428: } else {
429: throw new IllegalArgumentException(
430: "No CDC platform installed");// NOI18N
431: }
432: }
433: });
434:
435: resultSet.add(h.getProjectDirectory());
436: dirPr = (dirPr != null) ? dirPr.getParentFile() : null;
437: if (dirPr != null && dirPr.exists()) {
438: ProjectChooser.setProjectsFolder(dirPr);
439: }
440: return resultSet;
441: }
442:
443: public void initialize(WizardDescriptor wiz) {
444: this .wiz = wiz;
445: FileObject template = Templates.getTemplate(wiz);
446: preferredName = template.getName();
447: this .wiz.putProperty("name", preferredName);
448: platform = (String) template.getAttribute("platform");
449:
450: this .wiz = wiz;
451: index = 0;
452: panels = createPanels();
453: // Make sure list of steps is accurate.
454: String[] steps = createSteps();
455: for (int i = 0; i < panels.length; i++) {
456: Component c = panels[i].getComponent();
457: if (steps[i] == null) {
458: // Default step name to component name of panel.
459: // Mainly useful for getting the name of the target
460: // chooser to appear in the list of steps.
461: steps[i] = c.getName();
462: }
463: if (c instanceof JComponent) { // assume Swing components
464: JComponent jc = (JComponent) c;
465: // Step #.
466: jc.putClientProperty(
467: "WizardPanel_contentSelectedIndex",
468: new Integer(i)); // NOI18N
469: // Step name (actually the whole list for reference).
470: jc.putClientProperty("WizardPanel_contentData", steps); // NOI18N
471: }
472: }
473: this .wiz.putProperty("additionalProperties", new Properties());
474: }
475:
476: public void uninitialize(WizardDescriptor wiz) {
477: this .wiz.putProperty("projdir", null);
478: this .wiz.putProperty("additionalProperties", null);
479: this .wiz.putProperty("projdir", null); //NOI18N
480: this .wiz.putProperty("name", null); //NOI18N
481: this .wiz.putProperty("mainClass", null); //NOI18N
482: this .wiz = null;
483: panels = null;
484: }
485:
486: public String name() {
487: return MessageFormat.format("{0} of {1}", new Object[] {
488: new Integer(index + 1), new Integer(panels.length) });
489: }
490:
491: public boolean hasNext() {
492: return index < panels.length - 1;
493: }
494:
495: public boolean hasPrevious() {
496: return index > 0;
497: }
498:
499: public void nextPanel() {
500: if (!hasNext()) {
501: throw new NoSuchElementException();
502: }
503: index++;
504: }
505:
506: public void previousPanel() {
507: if (!hasPrevious()) {
508: throw new NoSuchElementException();
509: }
510: index--;
511: }
512:
513: public WizardDescriptor.Panel current() {
514: return panels[index];
515: }
516:
517: // If nothing unusual changes in the middle of the wizard, simply:
518: public final void addChangeListener(ChangeListener l) {
519: }
520:
521: public final void removeChangeListener(ChangeListener l) {
522: }
523:
524: private static void unZipFile(InputStream source,
525: FileObject projectRoot) throws IOException {
526: try {
527: ZipInputStream str = new ZipInputStream(source);
528: ZipEntry entry;
529: while ((entry = str.getNextEntry()) != null) {
530: if (entry.isDirectory()) {
531: FileUtil.createFolder(projectRoot, entry.getName());
532: } else {
533: FileObject fo = FileUtil.createData(projectRoot,
534: entry.getName());
535: FileLock lock = fo.lock();
536: try {
537: OutputStream out = fo.getOutputStream(lock);
538: try {
539: FileUtil.copy(str, out);
540: } finally {
541: out.close();
542: }
543: } finally {
544: lock.releaseLock();
545: }
546: }
547: }
548: } finally {
549: source.close();
550: }
551: }
552:
553: /**
554: * Create a new application manifest file with minimal initial contents.
555: * @param dir the directory to create it in
556: * @param path the relative path of the file
557: * @throws IOException in case of problems
558: */
559: private static void createManifest(FileObject dir, String path)
560: throws IOException {
561: FileObject manifest = dir.createData(MANIFEST_FILE);
562: FileLock lock = manifest.lock();
563: try {
564: OutputStream os = manifest.getOutputStream(lock);
565: try {
566: PrintWriter pw = new PrintWriter(os);
567: pw.println("Manifest-Version: 1.0"); // NOI18N
568: pw
569: .println("X-COMMENT: Main-Class will be added automatically by build"); // NOI18N
570: pw.println(); // safest to end in \n\n due to JRE parsing bug
571: pw.flush();
572: } finally {
573: os.close();
574: }
575: } finally {
576: lock.releaseLock();
577: }
578: }
579:
580: static int getNumberOfSuitableCdcPlatforms(String platformType) {
581: Set<String> accepted = null;
582: if (platformType != null) {
583: accepted = new HashSet<String>();
584: StringTokenizer st = new StringTokenizer(platformType, ",");
585: while (st.hasMoreTokens()) {
586: accepted.add(st.nextToken());
587: }
588: }
589:
590: JavaPlatform[] platforms = JavaPlatformManager.getDefault()
591: .getPlatforms(
592: null,
593: new Specification(CDCPlatform.PLATFORM_CDC,
594: null)); //NOI18N
595: if (accepted == null)
596: return platforms.length;
597:
598: List<JavaPlatform> plf = new ArrayList<JavaPlatform>();
599: for (JavaPlatform platform : platforms) {
600: if (accepted.contains(((CDCPlatform) platform).getType()))
601: plf.add(platform);
602: }
603: return plf.size();
604: }
605: }
|