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.project.ui.customizer;
043:
044: /**
045: *
046: * @author Administrator
047: */
048:
049: import java.awt.*;
050: import java.awt.event.ActionEvent;
051: import java.awt.event.ActionListener;
052: import java.io.IOException;
053: import java.io.OutputStream;
054: import java.lang.reflect.Method;
055: import java.util.Comparator;
056: import java.util.Enumeration;
057: import java.util.HashSet;
058: import java.util.Map;
059: import java.util.Properties;
060: import java.util.TreeSet;
061: import javax.swing.*;
062: import javax.swing.event.ChangeEvent;
063: import javax.swing.event.ChangeListener;
064: import javax.swing.event.ListSelectionEvent;
065: import javax.swing.event.ListSelectionListener;
066: import org.netbeans.api.java.platform.JavaPlatform;
067: import org.netbeans.api.java.platform.JavaPlatformManager;
068: import org.netbeans.api.java.platform.Specification;
069: import org.netbeans.modules.mobility.project.ui.wizard.ConfigurationsSelectionPanel;
070: import org.netbeans.spi.mobility.cfgfactory.ProjectConfigurationFactory.ConfigurationTemplateDescriptor;
071: import org.netbeans.spi.project.ProjectConfiguration;
072: import org.openide.DialogDisplayer;
073: import org.openide.ErrorManager;
074: import org.openide.NotifyDescriptor;
075: import org.openide.DialogDescriptor;
076: import org.openide.filesystems.FileLock;
077: import org.openide.filesystems.FileObject;
078: import org.openide.filesystems.FileSystem.AtomicAction;
079: import org.openide.filesystems.FileUtil;
080: import org.openide.filesystems.Repository;
081: import org.openide.util.HelpCtx;
082: import org.openide.util.NbBundle;
083: import org.netbeans.spi.project.support.ant.AntProjectHelper;
084: import org.netbeans.spi.project.support.ant.EditableProperties;
085: import org.openide.util.Utilities;
086: import org.netbeans.modules.mobility.cldcplatform.J2MEPlatform;
087: import org.netbeans.modules.mobility.project.DefaultPropertiesDescriptor;
088: import org.netbeans.modules.mobility.project.UserConfigurationTemplatesProvider;
089: import org.netbeans.modules.mobility.project.ui.wizard.ConfigurationsSelectionPanelGUI;
090:
091: /** Handles adding, removing, editing and ordering of configs.
092: *
093: * @author gc149856
094: */
095: public final class VisualConfigSupport {
096:
097: static final String PRIVATE_PREFIX = "private."; //NOI18N
098:
099: final JList configurationList;
100: final JButton addConfigButton;
101: final JButton addMoreButton;
102: final JButton renameConfigButton;
103: final JButton removeConfigButton;
104: final JButton duplicateButton;
105: final JButton saveButton;
106:
107: private final DefaultListModel configurationModel;
108:
109: J2MEProjectProperties properties;
110:
111: public VisualConfigSupport(JList configurationList,
112: JButton addConfigButton, JButton addMoreButton,
113: JButton renameConfigButton, JButton removeConfigButton,
114: JButton duplicateButton, JButton saveButton) {
115: // Remember all controls
116: this .configurationList = configurationList;
117: this .configurationModel = new DefaultListModel();
118: this .configurationList.setModel(configurationModel);
119: this .configurationList
120: .setCellRenderer(new ConfigurationCellRenderer());
121:
122: this .addConfigButton = addConfigButton;
123: this .addMoreButton = addMoreButton;
124: this .renameConfigButton = renameConfigButton;
125: this .removeConfigButton = removeConfigButton;
126: this .duplicateButton = duplicateButton;
127: this .saveButton = saveButton;
128:
129: // Register the listeners
130: ConfigSupportListener csl = new ConfigSupportListener();
131:
132: // On all buttons
133: addConfigButton.addActionListener(csl);
134: addMoreButton.addActionListener(csl);
135: renameConfigButton.addActionListener(csl);
136: removeConfigButton.addActionListener(csl);
137: duplicateButton.addActionListener(csl);
138: saveButton.addActionListener(csl);
139:
140: // On list selection
141: configurationList.getSelectionModel().addListSelectionListener(
142: csl);
143:
144: }
145:
146: public void setPropertyMap(final J2MEProjectProperties properties) {
147: this .properties = properties;
148: final ProjectConfiguration configurations[] = properties
149: .getConfigurations();
150: synchronized (configurationModel) {
151: configurationModel.clear();
152: for (int i = 0; i < configurations.length; i++) {
153: configurationModel.addElement(configurations[i]);
154: }
155: }
156: configurationList.setSelectedValue(properties
157: .getActiveConfiguration(), true);
158:
159: // Set the initial state of the buttons
160: refreshButtons();
161: }
162:
163: // Private methods ---------------------------------------------------------
164:
165: private ProjectConfiguration[] getConfigurationItems() {
166: synchronized (configurationModel) {
167: ProjectConfiguration confs[] = new ProjectConfiguration[configurationModel
168: .getSize()];
169: for (int i = 0; i < confs.length; i++) {
170: confs[i] = (ProjectConfiguration) configurationModel
171: .getElementAt(i);
172: }
173: return confs;
174: }
175: }
176:
177: protected void addNewConfig() {
178: final ProjectConfiguration cfgs[] = getConfigurationItems();
179: final HashSet<String> allNames = new HashSet<String>(
180: cfgs.length);
181: for (int i = 0; i < cfgs.length; i++) {
182: allNames.add(cfgs[i].getDisplayName());
183: }
184: final NewConfigurationPanel ncp = new NewConfigurationPanel(
185: allNames);
186: final DialogDescriptor dd = new DialogDescriptor(ncp, NbBundle
187: .getMessage(VisualConfigSupport.class,
188: "LBL_VCS_AddConfiguration"), true,
189: NotifyDescriptor.OK_CANCEL_OPTION,
190: NotifyDescriptor.OK_OPTION, null); //NOI18N
191: ncp.getAccessibleContext().setAccessibleName(
192: NbBundle.getMessage(VisualConfigSupport.class,
193: "LBL_VCS_AddConfiguration"));
194: ncp.getAccessibleContext().setAccessibleDescription(
195: NbBundle.getMessage(VisualConfigSupport.class,
196: "LBL_VCS_AddConfiguration"));
197: ncp.setDialogDescriptor(dd);
198: final String newName = NotifyDescriptor.OK_OPTION
199: .equals(DialogDisplayer.getDefault().notify(dd)) ? ncp
200: .getName() : null;
201: if (newName != null) {
202: final ProjectConfiguration cfg = new ProjectConfiguration() {
203: public String getDisplayName() {
204: return newName;
205: }
206: };
207: configurationModel.addElement(cfg);
208: configurationList.setSelectedValue(cfg, true);
209: createFromTemplate(properties, newName, ncp.getTemplate());
210: fireActionPerformed();
211: }
212:
213: }
214:
215: protected void addMoreConfigs() {
216: final ProjectConfiguration cfgs[] = getConfigurationItems();
217: final HashSet<String> allNames = new HashSet<String>(
218: cfgs.length);
219: for (int i = 0; i < cfgs.length; i++) {
220: allNames.add(cfgs[i].getDisplayName());
221: }
222: final ConfigurationsSelectionPanelGUI ncp = new ConfigurationsSelectionPanelGUI(
223: allNames);
224: ncp.getAccessibleContext().setAccessibleName(
225: NbBundle.getMessage(VisualConfigSupport.class,
226: "LBL_VCS_AddConfiguration"));
227: ncp.getAccessibleContext().setAccessibleDescription(
228: NbBundle.getMessage(VisualConfigSupport.class,
229: "LBL_VCS_AddConfiguration"));
230: final ErrorPanel ep = new ErrorPanel();
231: final JPanel p = new JPanel(new BorderLayout());
232: p.add(ncp, BorderLayout.CENTER);
233: p.add(ep, BorderLayout.SOUTH);
234: final DialogDescriptor dd = new DialogDescriptor(p, NbBundle
235: .getMessage(VisualConfigSupport.class,
236: "LBL_VCS_AddConfiguration"), true,
237: NotifyDescriptor.OK_CANCEL_OPTION,
238: NotifyDescriptor.OK_OPTION, null); //NOI18N
239: ncp.addChangeListener(new ChangeListener() {
240: public void stateChanged(ChangeEvent arg0) {
241: boolean valid = ncp.isValid();
242: dd.setValid(valid);
243: ep.setErrorMessage(valid ? null : NbBundle.getMessage(
244: ConfigurationsSelectionPanel.class,
245: "ERR_CfgSelPanel_NameCollision"));//NOI18N
246: }
247: });
248: if (NotifyDescriptor.OK_OPTION.equals(DialogDisplayer
249: .getDefault().notify(dd))) {
250: for (ConfigurationTemplateDescriptor tmp : ncp
251: .getSelectedTemplates()) {
252: final String newName = tmp.getCfgName();
253: final ProjectConfiguration cfg = new ProjectConfiguration() {
254: public String getDisplayName() {
255: return newName;
256: }
257: };
258: configurationModel.addElement(cfg);
259: configurationList.setSelectedValue(cfg, true);
260: createFromTemplate(properties, newName, tmp);
261: }
262: fireActionPerformed();
263: }
264:
265: }
266:
267: public static void createFromTemplate(
268: final J2MEProjectProperties properties, final String cfg,
269: final ConfigurationTemplateDescriptor desc) {
270: if (desc == null)
271: return;
272: AntProjectHelper helper = properties.getHelper();
273: final EditableProperties priv = helper
274: .getProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH);
275: final EditableProperties proj = helper
276: .getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
277: String cfgName = desc.getCfgName();
278: String prefix = J2MEProjectProperties.CONFIG_PREFIX + cfgName
279: + '.';
280: Map<String, String> p = desc.getPrivateProperties();
281: if (p != null)
282: for (Map.Entry<String, String> en : p.entrySet()) {
283: if (!priv.containsKey(en.getKey()))
284: priv.put(en.getKey(), en.getValue());
285: }
286: p = desc.getProjectGlobalProperties();
287: if (p != null)
288: for (Map.Entry<String, String> en : p.entrySet()) {
289: if (!proj.containsKey(en.getKey()))
290: proj.put(en.getKey(), en.getValue());
291: }
292: p = desc.getProjectConfigurationProperties();
293: if (p != null)
294: for (Map.Entry<String, String> en : p.entrySet()) {
295: properties.putPropertyRawValue(
296: J2MEProjectProperties.CONFIG_PREFIX + cfg + '.'
297: + en.getKey(), en.getValue());
298: }
299: helper.putProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH,
300: priv);
301: helper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH,
302: proj);
303: }
304:
305: private static void fixPlatform(
306: final J2MEProjectProperties properties,
307: final String configuration, final String platform) {
308: final JavaPlatform p[] = JavaPlatformManager.getDefault()
309: .getPlatforms(
310: null,
311: new Specification(
312: J2MEPlatform.SPECIFICATION_NAME, null));
313: int best = 0, rating = 0;
314: for (int i = 0; rating < 5 && i < p.length; i++) {
315: if (p[i] instanceof J2MEPlatform) {
316: final int r = ratePlatform((J2MEPlatform) p[i],
317: platform);
318: if (r > rating) {
319: rating = r;
320: best = i;
321: }
322: }
323: }
324: if (rating > 0) {
325: properties
326: .putPropertyRawValue(
327: J2MEProjectProperties.CONFIG_PREFIX
328: + configuration
329: + '.'
330: + DefaultPropertiesDescriptor.PLATFORM_ACTIVE,
331: ((J2MEPlatform) p[best]).getName());
332: final CustomizerMIDP cmp = new CustomizerMIDP();
333: cmp.initValues(properties, configuration);
334: cmp.initGroupValues(true);
335: }
336: }
337:
338: private static int ratePlatform(final J2MEPlatform platform,
339: final String expName) {
340: final String name = platform.getName();
341: if (name.equals(expName))
342: return 5;
343: if (name.indexOf(expName) >= 0)
344: return 4;
345: if (name.startsWith("J2ME_Wireless_Toolkit_2"))
346: return 3;//NOI18N
347: if (name.startsWith("J2ME_Wireless_Toolkit"))
348: return 2;//NOI18N
349: return 1;
350: }
351:
352: protected void duplicateElement() {
353: final Object cfgs[] = configurationList.getSelectedValues();
354: assert cfgs.length > 0 : "Duplicate button should be disabled"; // NOI18N
355: final ProjectConfiguration allCfgs[] = getConfigurationItems();
356: final HashSet<String> allNames = new HashSet<String>(
357: allCfgs.length);
358: for (int i = 0; i < allCfgs.length; i++) {
359: allNames.add(allCfgs[i].getDisplayName());
360: }
361: if (cfgs.length == 1) {
362: final CloneConfigurationPanel ccp = new CloneConfigurationPanel(
363: allNames);
364: final DialogDescriptor dd = new DialogDescriptor(ccp,
365: NbBundle.getMessage(VisualConfigSupport.class,
366: "LBL_VCS_DuplConfiguration",
367: ((ProjectConfiguration) cfgs[0])
368: .getDisplayName()), true,
369: NotifyDescriptor.OK_CANCEL_OPTION,
370: NotifyDescriptor.OK_OPTION, null); //NOI18N
371: ccp.setDialogDescriptor(dd);
372: final String newName = NotifyDescriptor.OK_OPTION
373: .equals(DialogDisplayer.getDefault().notify(dd)) ? ccp
374: .getName()
375: : null;
376: if (newName != null) {
377: copyProperties(((ProjectConfiguration) cfgs[0])
378: .getDisplayName(), newName);
379: configurationList.setSelectedValue(addCfg(newName),
380: true);
381: fireActionPerformed();
382: }
383: } else {
384: final HashSet<String> cloneNames = new HashSet<String>(
385: cfgs.length);
386: for (int i = 0; i < cfgs.length; i++) {
387: cloneNames.add(((ProjectConfiguration) cfgs[i])
388: .getDisplayName());
389: }
390: final CloneConfigurationPanel2 ccp = new CloneConfigurationPanel2(
391: allNames, cloneNames);
392: final DialogDescriptor dd = new DialogDescriptor(ccp,
393: NbBundle.getMessage(VisualConfigSupport.class,
394: "LBL_VCS_DuplConfigurations"), true,
395: NotifyDescriptor.OK_CANCEL_OPTION,
396: NotifyDescriptor.OK_OPTION, null); //NOI18N
397: ccp.setDialogDescriptor(dd);
398: if (NotifyDescriptor.OK_OPTION.equals(DialogDisplayer
399: .getDefault().notify(dd))) {
400: String prefix = ccp.getPrefix();
401: String suffix = ccp.getSuffix();
402: for (int i = 0; i < cfgs.length; i++) {
403: ProjectConfiguration cfg = (ProjectConfiguration) cfgs[i];
404: String newName = prefix + cfg.getDisplayName()
405: + suffix;
406: copyProperties(cfg.getDisplayName(), newName);
407: configurationList.setSelectedValue(addCfg(newName),
408: true);
409: }
410: fireActionPerformed();
411: }
412: }
413: }
414:
415: private ProjectConfiguration addCfg(final String newName) {
416: final ProjectConfiguration newCfg = new ProjectConfiguration() {
417: public String getDisplayName() {
418: return newName;
419: }
420: };
421: configurationModel.addElement(newCfg);
422: return newCfg;
423: }
424:
425: private void copyProperties(final String srcCfg,
426: final String targetCfg) {
427: final String keys[] = properties.keySet().toArray(
428: new String[properties.size()]);
429: final String prefix = J2MEProjectProperties.CONFIG_PREFIX
430: + srcCfg;
431: for (int i = 0; i < keys.length; i++) {
432: if (keys[i].startsWith(prefix)) {
433: Object backValue = properties.get(keys[i]);
434: if (backValue instanceof Cloneable)
435: try {
436: Method m = backValue.getClass().getMethod(
437: "clone", new Class[0]); //NOI18N
438: if (m != null)
439: backValue = m.invoke(backValue,
440: new Object[0]);
441: } catch (Exception e) {
442: ErrorManager.getDefault().notify(
443: ErrorManager.INFORMATIONAL, e);
444: }
445: properties
446: .put(J2MEProjectProperties.CONFIG_PREFIX
447: + targetCfg
448: + keys[i].substring(prefix.length()),
449: backValue);
450: }
451: }
452: }
453:
454: protected void removeElement() {
455: final int si = configurationList.getSelectedIndex();
456: assert si > 0 : "Remove button should be disabled"; // NOI18N
457: Object cfgs[] = configurationList.getSelectedValues();
458: StringBuffer text = new StringBuffer(
459: ((ProjectConfiguration) cfgs[0]).getDisplayName()); //NOI18N
460: for (int i = 1; i < cfgs.length; i++)
461: text.append("\", \"").append(
462: ((ProjectConfiguration) cfgs[i]).getDisplayName()); //NOI18N
463: final NotifyDescriptor desc = new NotifyDescriptor.Confirmation(
464: NbBundle.getMessage(VisualConfigSupport.class,
465: "LBL_VCS_ReallyRemove", text),
466: NotifyDescriptor.YES_NO_OPTION); //NOI18N
467: if (NotifyDescriptor.YES_OPTION.equals(DialogDisplayer
468: .getDefault().notify(desc))) {
469: for (int i = cfgs.length - 1; i >= 0; i--) {
470: configurationModel.removeElement(cfgs[i]);
471: removeProperties(((ProjectConfiguration) cfgs[i])
472: .getDisplayName());
473: }
474: configurationList.setSelectedIndex(si < configurationModel
475: .getSize() ? si : si - 1);
476: fireActionPerformed();
477: }
478: }
479:
480: protected void renameElement() {
481: final Object cfgs[] = configurationList.getSelectedValues();
482: assert cfgs.length > 0 : "Rename button should be disabled"; // NOI18N
483: for (Object o : cfgs) {
484: ProjectConfiguration cfg = (ProjectConfiguration) o;
485: final ProjectConfiguration allCfgs[] = getConfigurationItems();
486: final HashSet<String> allNames = new HashSet<String>(
487: allCfgs.length);
488: for (int i = 0; i < allCfgs.length; i++) {
489: allNames.add(allCfgs[i].getDisplayName());
490: }
491: final CloneConfigurationPanel ccp = new CloneConfigurationPanel(
492: allNames);
493: final DialogDescriptor dd = new DialogDescriptor(ccp,
494: NbBundle.getMessage(VisualConfigSupport.class,
495: "LBL_VCS_RenConfiguration", cfg
496: .getDisplayName()), true,
497: NotifyDescriptor.OK_CANCEL_OPTION,
498: NotifyDescriptor.OK_OPTION, null); //NOI18N
499: ccp.setDialogDescriptor(dd);
500: Object ret = DialogDisplayer.getDefault().notify(dd);
501: if (NotifyDescriptor.OK_OPTION.equals(ret)) {
502: String newName = ccp.getName();
503: copyProperties(cfg.getDisplayName(), newName);
504: removeProperties(cfg.getDisplayName());
505: configurationModel.removeElement(cfg);
506: configurationList.setSelectedValue(addCfg(newName),
507: true);
508: fireActionPerformed();
509: } else if (NotifyDescriptor.CANCEL_OPTION.equals(ret))
510: return;
511: }
512: }
513:
514: private void removeProperties(final String cfgName) {
515: final String keys[] = properties.keySet().toArray(
516: new String[properties.size()]);
517: final String prefix = J2MEProjectProperties.CONFIG_PREFIX
518: + cfgName;
519: for (int i = 0; i < keys.length; i++) {
520: if (keys[i].startsWith(prefix))
521: properties.remove(keys[i]);
522: }
523: }
524:
525: protected void saveElement() {
526: final Object cfgs[] = configurationList.getSelectedValues();
527: assert cfgs.length > 0 : "Save button should be disabled"; // NOI18N
528: final FileObject[] tmps = getConfigurationTemplates();
529: final HashSet<String> allNames = new HashSet<String>();
530: for (int i = 0; i < tmps.length; i++) {
531: allNames.add(tmps[i].getName());
532: }
533: final JButton SAVE_OPTION = new JButton(NbBundle.getMessage(
534: VisualConfigSupport.class, "LBL_VCS_SaveBtn")); //NOI18N
535: SAVE_OPTION
536: .setMnemonic(NbBundle.getMessage(
537: VisualConfigSupport.class, "MNM_VCS_SaveBtn")
538: .charAt(0)); //NOI18N
539: SAVE_OPTION.getAccessibleContext().setAccessibleDescription(
540: NbBundle.getMessage(VisualConfigSupport.class,
541: "ACSD_VCS_SaveBtn")); //NOI18N
542: for (Object o : cfgs) {
543: ProjectConfiguration cfg = (ProjectConfiguration) o;
544: final SaveConfigurationPanel scp = new SaveConfigurationPanel(
545: cfg.getDisplayName()
546: + UserConfigurationTemplatesProvider.CFG_TEMPLATE_SUFFIX,
547: allNames, SAVE_OPTION);
548: final DialogDescriptor dd = new DialogDescriptor(scp,
549: NbBundle.getMessage(VisualConfigSupport.class,
550: "LBL_VCS_SaveConfiguration", cfg
551: .getDisplayName()), true,
552: new Object[] { SAVE_OPTION,
553: NotifyDescriptor.CANCEL_OPTION },
554: SAVE_OPTION, DialogDescriptor.DEFAULT_ALIGN,
555: new HelpCtx(SaveConfigurationPanel.class), null); //NOI18N
556: Object ret = DialogDisplayer.getDefault().notify(dd);
557: if (SAVE_OPTION.equals(ret)) {
558: saveConfigurationTemplate(cfg.getDisplayName(), scp
559: .getName());
560: } else if (DialogDescriptor.CANCEL_OPTION.equals(ret))
561: return;
562: }
563: }
564:
565: public static FileObject[] getConfigurationTemplates() {
566: final TreeSet<FileObject> a = new TreeSet<FileObject>(
567: new Comparator<FileObject>() {
568: public int compare(FileObject o1, FileObject o2) {
569: return o1.getName().compareTo(o2.getName());
570: }
571: });
572: final FileObject dir = Repository
573: .getDefault()
574: .getDefaultFileSystem()
575: .findResource(
576: UserConfigurationTemplatesProvider.CFG_TEMPLATES_PATH);
577: if (dir != null) {
578: final Enumeration en = dir.getData(false);
579: while (en.hasMoreElements()) {
580: final FileObject fo = (FileObject) en.nextElement();
581: if (UserConfigurationTemplatesProvider.CFG_EXT
582: .equals(fo.getExt())
583: && Utilities.isJavaIdentifier(fo.getName()))
584: a.add(fo);
585: }
586: }
587: return a.toArray(new FileObject[a.size()]);
588: }
589:
590: private void saveConfigurationTemplate(final String cfgName,
591: final String tmpName) {
592: try {
593: Repository.getDefault().getDefaultFileSystem()
594: .runAtomicAction(new AtomicAction() {
595: public void run() {
596: FileLock lock = null;
597: OutputStream out = null;
598: try {
599: final FileObject fo = FileUtil
600: .createData(
601: Repository
602: .getDefault()
603: .getDefaultFileSystem()
604: .getRoot(),
605: UserConfigurationTemplatesProvider.CFG_TEMPLATES_PATH
606: + '/'
607: + tmpName
608: + '.'
609: + UserConfigurationTemplatesProvider.CFG_EXT);
610: lock = fo.lock();
611: out = fo.getOutputStream(lock);
612: extractConfigurationTemplate(cfgName,
613: tmpName).store(out, null);
614: } catch (Exception e) {
615: ErrorManager.getDefault().notify(e);
616: } finally {
617: if (out != null)
618: try {
619: out.close();
620: } catch (IOException ioe) {
621: }
622: if (lock != null)
623: lock.releaseLock();
624: }
625: }
626: });
627: } catch (IOException ex) {
628: ErrorManager.getDefault().notify(ex);
629: }
630: }
631:
632: protected Properties extractConfigurationTemplate(
633: final String cfgName, final String tmpName) {
634: final Properties props = new Properties();
635: final String keys[] = properties.keySet().toArray(
636: new String[properties.size()]);
637: final String prefix = J2MEProjectProperties.CONFIG_PREFIX
638: + cfgName + '.';
639: final String newPrefix = J2MEProjectProperties.CONFIG_PREFIX
640: + tmpName + '.';
641: final String libs = J2MEProjectProperties.CONFIG_PREFIX
642: + cfgName + '.'
643: + DefaultPropertiesDescriptor.LIBS_CLASSPATH;
644: final int prefixL = prefix.length();
645: String references = null;
646: for (int i = 0; i < keys.length; i++) {
647: if (keys[i].startsWith(prefix)) {
648: final String value = properties
649: .getPropertyRawValue(keys[i]);
650: if (value != null) {
651: props.put(newPrefix + keys[i].substring(prefixL),
652: value);
653: if (libs.equals(keys[i]))
654: references = value;
655: }
656: }
657: }
658: if (references != null)
659: processReferences(props, references, properties.getHelper()
660: .getProperties(
661: AntProjectHelper.PROJECT_PROPERTIES_PATH),
662: properties.getHelper().getProperties(
663: AntProjectHelper.PRIVATE_PROPERTIES_PATH));
664: return props;
665: }
666:
667: private void processReferences(final Properties props,
668: final String path, final EditableProperties pub,
669: final EditableProperties priv) {
670: int i, j = 0;
671: while ((i = path.indexOf("${", j)) >= 0) { //NOI18N
672: if ((j = path.indexOf('}', i)) < 0)
673: return;
674: final String reference = path.substring(i + 2, j);
675: if (!props.contains(reference)
676: && !props.contains(PRIVATE_PREFIX + reference)) {
677: String value = priv.getProperty(reference);
678: if (value != null) {
679: props.put(PRIVATE_PREFIX + reference, value);
680: processReferences(props, value, pub, priv);
681: }
682: value = pub.getProperty(reference);
683: if (value != null) {
684: if (value.indexOf('$') < 0) {
685: //probably a relative path references that should be stores in an absolute form in private properties
686: props.put(PRIVATE_PREFIX + reference,
687: properties.getHelper().resolvePath(
688: value));
689: } else {
690: props.put(reference, value);
691: processReferences(props, value, pub, priv);
692: }
693: }
694: }
695: }
696: }
697:
698: // Private innerclasses ----------------------------------------------------
699:
700: private class ConfigSupportListener implements ActionListener,
701: ListSelectionListener {
702:
703: private ConfigSupportListener() {
704: //Just to avoid creation of accessor class
705: }
706:
707: // Implementation of ActionListener ------------------------------------
708:
709: /** Handles button events
710: */
711: public void actionPerformed(final ActionEvent e) {
712:
713: final Object source = e.getSource();
714:
715: if (source == addConfigButton) {
716: addNewConfig();
717: } else if (source == addMoreButton) {
718: addMoreConfigs();
719: } else if (source == renameConfigButton) {
720: renameElement();
721: } else if (source == removeConfigButton) {
722: removeElement();
723: } else if (source == duplicateButton) {
724: duplicateElement();
725: } else if (source == saveButton) {
726: saveElement();
727: }
728:
729: }
730:
731: // ListSelectionModel --------------------------------------------------
732:
733: /** Handles changes in the selection
734: */
735: public void valueChanged(@SuppressWarnings("unused")
736: final ListSelectionEvent e) {
737: refreshButtons();
738: properties
739: .setActiveConfiguration((ProjectConfiguration) configurationList
740: .getSelectedValue());
741: }
742:
743: }
744:
745: protected void refreshButtons() {
746: final boolean sel = configurationList.getSelectedIndex() > 0;
747: renameConfigButton.setEnabled(sel);
748: removeConfigButton.setEnabled(sel);
749: duplicateButton.setEnabled(sel);
750: saveButton.setEnabled(sel);
751: }
752:
753: private void fireActionPerformed() {
754: refreshButtons();
755: properties.setConfigurations(getConfigurationItems());
756: properties
757: .setActiveConfiguration((ProjectConfiguration) configurationList
758: .getSelectedValue());
759: }
760:
761: private static class ConfigurationCellRenderer extends
762: DefaultListCellRenderer {
763:
764: private ConfigurationCellRenderer() {
765: //Just to avoid creation of accessor class
766: }
767:
768: public Component getListCellRendererComponent(final JList list,
769: final Object value, final int index,
770: final boolean isSelected, final boolean cellHasFocus) {
771: super .getListCellRendererComponent(list, value, index,
772: isSelected, cellHasFocus);
773: if (value instanceof ProjectConfiguration) {
774: setText(((ProjectConfiguration) value).getDisplayName());
775: }
776: return this;
777: }
778:
779: }
780:
781: }
|