PageRenderTime 90ms CodeModel.GetById 16ms RepoModel.GetById 2ms app.codeStats 0ms

/projects/netbeans-7.3/mobility.project/src/org/netbeans/modules/mobility/project/ProjectConfigurationsHelper.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 538 lines | 384 code | 44 blank | 110 comment | 84 complexity | 4d3473227e4312819f2fea17d5d76650 MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  5. *
  6. * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  7. * Other names may be trademarks of their respective owners.
  8. *
  9. * The contents of this file are subject to the terms of either the GNU
  10. * General Public License Version 2 only ("GPL") or the Common
  11. * Development and Distribution License("CDDL") (collectively, the
  12. * "License"). You may not use this file except in compliance with the
  13. * License. You can obtain a copy of the License at
  14. * http://www.netbeans.org/cddl-gplv2.html
  15. * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  16. * specific language governing permissions and limitations under the
  17. * License. When distributing the software, include this License Header
  18. * Notice in each file and include the License file at
  19. * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
  20. * particular file as subject to the "Classpath" exception as provided
  21. * by Oracle in the GPL Version 2 section of the License file that
  22. * accompanied this code. If applicable, add the following below the
  23. * License Header, with the fields enclosed by brackets [] replaced by
  24. * your own identifying information:
  25. * "Portions Copyrighted [year] [name of copyright owner]"
  26. *
  27. * Contributor(s):
  28. *
  29. * The Original Software is NetBeans. The Initial Developer of the Original
  30. * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  31. * Microsystems, Inc. All Rights Reserved.
  32. *
  33. * If you wish your version of this file to be governed by only the CDDL
  34. * or only the GPL Version 2, indicate your decision by adding
  35. * "[Contributor] elects to include this software in this distribution
  36. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  37. * single choice of license, a recipient has the option to distribute
  38. * your version of this file under either the CDDL, the GPL Version 2 or
  39. * to extend the choice of license to its licensees as provided above.
  40. * However, if you add GPL Version 2 code and therefore, elected the GPL
  41. * Version 2 license, then the option applies only if the new code is
  42. * made subject to such option by the copyright holder.
  43. */
  44. package org.netbeans.modules.mobility.project;
  45. import java.awt.BorderLayout;
  46. import java.awt.Dialog;
  47. import java.awt.EventQueue;
  48. import java.awt.event.WindowAdapter;
  49. import java.awt.event.WindowEvent;
  50. import java.beans.PropertyChangeListener;
  51. import java.beans.PropertyChangeSupport;
  52. import java.io.IOException;
  53. import java.util.Arrays;
  54. import java.util.Collection;
  55. import java.util.Collections;
  56. import java.util.Comparator;
  57. import java.util.HashMap;
  58. import java.util.Map;
  59. import java.util.Set;
  60. import java.util.TreeMap;
  61. import java.util.TreeSet;
  62. import javax.swing.JComponent;
  63. import javax.swing.JDialog;
  64. import javax.swing.JLabel;
  65. import javax.swing.JPanel;
  66. import javax.swing.SwingUtilities;
  67. import org.netbeans.api.progress.ProgressHandle;
  68. import org.netbeans.api.progress.ProgressHandleFactory;
  69. import org.netbeans.api.project.ProjectManager;
  70. import org.netbeans.modules.mobility.project.ui.J2MECustomizerProvider;
  71. import org.netbeans.spi.project.ProjectConfiguration;
  72. import org.netbeans.spi.project.ProjectConfigurationProvider;
  73. import org.netbeans.mobility.antext.preprocessor.CommentingPreProcessor;
  74. import org.netbeans.modules.mobility.project.ui.customizer.J2MEProjectProperties;
  75. import org.netbeans.spi.project.support.ant.AntProjectEvent;
  76. import org.netbeans.spi.project.support.ant.AntProjectHelper;
  77. import org.netbeans.spi.project.support.ant.AntProjectListener;
  78. import org.netbeans.spi.project.support.ant.EditableProperties;
  79. import org.openide.ErrorManager;
  80. import org.openide.util.Exceptions;
  81. import org.openide.util.Mutex;
  82. import org.openide.util.Mutex.Action;
  83. import org.openide.util.MutexException;
  84. import org.openide.util.NbBundle;
  85. import org.openide.util.RequestProcessor;
  86. import org.openide.windows.WindowManager;
  87. /**
  88. * Helper class implementing ProjectConfigurationProvider for Ant based projects.
  89. * @author Adam Sotona, David Kaspar
  90. */
  91. public final class ProjectConfigurationsHelper implements ProjectConfigurationProvider<ProjectConfiguration>, AntProjectListener {
  92. /**
  93. * name of the Ant property storing the active configuration
  94. */
  95. public static final String PROJ_PROP_CONFIGURATION_ACTIVE = "config.active"; // NOI18N
  96. /**
  97. * Default configuration name.
  98. */
  99. static public final String DEFAULT_CONFIGURATION_NAME = "DefaultConfiguration"; // NOI18N
  100. /**
  101. * Default configuration name.
  102. */
  103. public static final String PROJECT_PROPERTIES = "ProjectProperties"; // NOI18N
  104. protected final AntProjectHelper h;
  105. private TreeMap<String,ProjectConfiguration> configurations;
  106. private PropertyChangeSupport psp;
  107. private ProjectConfiguration activeConfiguration;
  108. //private ProjectConfiguration[] configurations;
  109. private ProjectConfiguration defaultConfiguration;
  110. private J2MEProject p;
  111. private boolean preprocessorOn, invalid = true;
  112. /**
  113. * Creates new instance of the helper.
  114. * @param helper AntProjectHelper for accessing Ant project properties.
  115. * @param emp ExtensibleMetadataProvider to access project XML.
  116. */
  117. public ProjectConfigurationsHelper(AntProjectHelper helper, J2MEProject p) {
  118. this.h = helper;
  119. this.p = p;
  120. }
  121. public boolean isPreprocessorOn() {
  122. if (invalid) {
  123. String prop = h.getStandardPropertyEvaluator().getProperty(DefaultPropertiesDescriptor.USE_PREPROCESSOR);
  124. preprocessorOn = prop == null || Boolean.parseBoolean(prop);
  125. invalid = false;
  126. }
  127. return preprocessorOn;
  128. }
  129. public ProjectConfiguration getDefaultConfiguration() {
  130. if (defaultConfiguration == null) {
  131. defaultConfiguration = createConfiguration(DEFAULT_CONFIGURATION_NAME); //NOI18N
  132. }
  133. return defaultConfiguration;
  134. }
  135. /**
  136. * Append new configuration to the project.
  137. * @param configName String new configuration name
  138. * @return boolean success
  139. */
  140. public final boolean addConfiguration(final String configName) {
  141. if (configName == null || configName.equals(getDefaultConfiguration().getDisplayName())) return false;
  142. boolean ret = (ProjectManager.mutex().writeAccess(new Mutex.Action<Boolean>() {
  143. public Boolean run() {
  144. EditableProperties props = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
  145. String cfgs = props.getProperty(DefaultPropertiesDescriptor.ALL_CONFIGURATIONS);
  146. if (cfgs == null) cfgs = ""; //NOI18N
  147. boolean add = true;
  148. StringBuffer sb = new StringBuffer(" ");
  149. for (String s : cfgs.split(",")) { //NOI18N
  150. if (s.trim().length() > 0) {
  151. int i = s.compareTo(configName);
  152. if (i == 0) return Boolean.FALSE;
  153. else if (add && i > 0) {
  154. add = false;
  155. sb.append(',').append(configName);
  156. }
  157. sb.append(',').append(s);
  158. }
  159. }
  160. if (add) {
  161. sb.append(',').append(configName);
  162. }
  163. props.put(DefaultPropertiesDescriptor.ALL_CONFIGURATIONS, sb.toString());
  164. h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props);
  165. return Boolean.TRUE;
  166. }
  167. })).booleanValue();
  168. try {
  169. ProjectManager.getDefault().saveProject(p);
  170. return ret;
  171. } catch (IOException ioe) {
  172. ErrorManager.getDefault().notify(ioe);
  173. }
  174. return false;
  175. }
  176. public Map<String,String> getAbilitiesFor(final ProjectConfiguration cfg) {
  177. final String abilities = J2MEProjectUtils.evaluateProperty(h, DefaultPropertiesDescriptor.ABILITIES, cfg.getDisplayName());
  178. final Map<String,String> m = abilities == null ? new HashMap<String,String>() : CommentingPreProcessor.decodeAbilitiesMap(abilities);
  179. m.put("DebugLevel", J2MEProjectUtils.evaluateProperty(h, DefaultPropertiesDescriptor.DEBUG_LEVEL, cfg.getDisplayName())); //NOI18N
  180. return m;
  181. }
  182. public Map<String,String> getActiveAbilities() {
  183. return getAbilitiesFor(getActiveConfiguration());
  184. }
  185. public Set<String> getAllIdentifiers(final boolean includeConfigNames) {
  186. final TreeSet<String> s = new TreeSet<String>();
  187. final ProjectConfiguration devConfigs[] = getConfigurations().toArray(new ProjectConfiguration[0]);
  188. for (int i=0; i<devConfigs.length; i++) {
  189. if (includeConfigNames) s.add(devConfigs[i].getDisplayName());
  190. final String propName = getDefaultConfiguration().equals(devConfigs[i]) ? DefaultPropertiesDescriptor.ABILITIES : J2MEProjectProperties.CONFIG_PREFIX + devConfigs[i].getDisplayName() + '.' + DefaultPropertiesDescriptor.ABILITIES;
  191. final String prop = h.getStandardPropertyEvaluator().getProperty(propName);
  192. if (prop != null) s.addAll(CommentingPreProcessor.decodeAbilitiesMap(prop).keySet());
  193. }
  194. return s;
  195. }
  196. /**
  197. * Remove configuration from project.
  198. * @param configName String configuration name
  199. * @return boolean success
  200. */
  201. public final boolean removeConfiguration(final ProjectConfiguration config) {
  202. if (config == null || config.equals(getDefaultConfiguration())) return false;
  203. boolean ret = (ProjectManager.mutex().writeAccess(new Mutex.Action<Boolean>() {
  204. public Boolean run() {
  205. EditableProperties props = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
  206. String cfgs = props.getProperty(DefaultPropertiesDescriptor.ALL_CONFIGURATIONS);
  207. if (cfgs == null) return Boolean.FALSE;
  208. boolean succ = false;
  209. StringBuffer sb = new StringBuffer();
  210. for (String s : cfgs.split(",")) { //NOI18N
  211. if (s.equals(config.getDisplayName())) {
  212. succ = true;
  213. } else {
  214. if (sb.length() > 0) sb.append(',');
  215. sb.append(s);
  216. }
  217. }
  218. if (succ) {
  219. final String projProp = "configs." + config.getDisplayName(); // NOI18N
  220. for (String key : props.keySet().toArray(new String[0])) {
  221. if (key.startsWith(projProp)) props.remove(key);
  222. }
  223. props.put(DefaultPropertiesDescriptor.ALL_CONFIGURATIONS, sb.toString());
  224. h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props);
  225. }
  226. return Boolean.valueOf(succ);
  227. }
  228. })).booleanValue();
  229. try {
  230. ProjectManager.getDefault().saveProject(p);
  231. return ret;
  232. } catch (IOException ioe) {
  233. ErrorManager.getDefault().notify(ioe);
  234. }
  235. return false;
  236. }
  237. /**
  238. * Implements ProjectConfigurationProvider.
  239. * Get list of project configuration names.
  240. * @return ProjectConfiguration[] list.
  241. */
  242. public final Collection<ProjectConfiguration> getConfigurations() {
  243. return getConfigurations(configurations);
  244. }
  245. private final Collection<ProjectConfiguration> getConfigurations(final TreeMap<String,ProjectConfiguration> oldConfig) {
  246. if (configurations == null) {
  247. configurations = ProjectManager.mutex().readAccess(new Mutex.Action<TreeMap<String,ProjectConfiguration>>() {
  248. public TreeMap<String,ProjectConfiguration> run() {
  249. final TreeMap<String,ProjectConfiguration> newByName = new TreeMap<String,ProjectConfiguration>(new Comparator<String>() {
  250. public int compare(String o1, String o2) {
  251. return DEFAULT_CONFIGURATION_NAME.equals(o1) ? (DEFAULT_CONFIGURATION_NAME.equals(o2) ? 0 : -1) : (DEFAULT_CONFIGURATION_NAME.equals(o2) ? 1 : o1.compareToIgnoreCase(o2));
  252. }
  253. });
  254. newByName.put(getDefaultConfiguration().getDisplayName(),getDefaultConfiguration());
  255. String cfgs = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH).getProperty(DefaultPropertiesDescriptor.ALL_CONFIGURATIONS);
  256. if (cfgs != null) {
  257. for (String configName : cfgs.split(",")) { //NOII8N
  258. if (configName.length() > 0 && !configName.equals(" ")) { //NOI18N
  259. ProjectConfiguration conf = oldConfig == null ? null : oldConfig.get(configName);
  260. newByName.put(configName, conf == null ? createConfiguration(configName) : conf);
  261. }
  262. }
  263. }
  264. return newByName;
  265. }
  266. });
  267. }
  268. return configurations == null ? null : Collections.unmodifiableCollection(configurations.values());
  269. }
  270. /**
  271. * Implements ProjectConfigurationProvider.
  272. * Allows listenning on configurations and active configuration.
  273. * @param lst PropertyChangeListener
  274. */
  275. public final void addPropertyChangeListener(final PropertyChangeListener lst) {
  276. synchronized (this) {
  277. if (psp == null) {
  278. psp = new PropertyChangeSupport(this);
  279. getConfigurations();
  280. getActiveConfiguration();
  281. h.addAntProjectListener(this);
  282. }
  283. }
  284. psp.addPropertyChangeListener(lst);
  285. }
  286. /**
  287. * Implements ProjectConfigurationProvider.
  288. * Get currently active configuration of the project.
  289. * @return String active configuration name.
  290. */
  291. public final ProjectConfiguration getActiveConfiguration() {
  292. if (activeConfiguration == null) {
  293. ProjectManager.mutex().readAccess(new Action<Boolean>(){
  294. public Boolean run(){
  295. activeConfiguration = getDefaultConfiguration();
  296. final String confName = h.getStandardPropertyEvaluator().getProperty(PROJ_PROP_CONFIGURATION_ACTIVE);
  297. if (confName == null || confName.length() == 0) {
  298. activeConfiguration = getDefaultConfiguration();
  299. return null;
  300. }
  301. final ProjectConfiguration confs[] = getConfigurations().toArray(new ProjectConfiguration[0]);
  302. for (int i = 0; i < confs.length; i++) {
  303. if (confName.equals((confs[i]).getDisplayName())) {
  304. activeConfiguration = confs[i];
  305. return null;
  306. }
  307. }
  308. return null;
  309. }
  310. });
  311. }
  312. return activeConfiguration;
  313. }
  314. /**
  315. * Helper method that returns ProjectConfiguration by name
  316. * @param configName name of the ProjectConfiguration to retrieve
  317. * @return ProjectConfiguration object that has the passed name
  318. */
  319. public final ProjectConfiguration getConfigurationByName(String configName) {
  320. return configurations.get(configName);
  321. }
  322. /**
  323. * Implements ProjectConfigurationProvider.
  324. * Removes listener on configurations and active configuration.
  325. * @param lst PropertyChangeListener
  326. */
  327. public final void removePropertyChangeListener(final PropertyChangeListener lst) {
  328. if (psp != null) psp.removePropertyChangeListener(lst);
  329. }
  330. protected ProjectConfiguration createConfiguration(final String configName) {
  331. return new ConfigurationImpl(configName);
  332. }
  333. /**
  334. * Implements ProjectConfigurationProvider.
  335. * Set the active configuration name.
  336. * Fire property change with PROP_CONFIGURATION_ACTIVE to all listeners.
  337. * @param configuration new active ProjectConfiguration
  338. */
  339. public final void setActiveConfiguration(final ProjectConfiguration configuration) throws IllegalArgumentException, IOException {
  340. final ProgressHandle handle = ProgressHandleFactory.createHandle(NbBundle.getMessage(ProjectConfigurationsHelper.class,
  341. "TTL_CHANGE_CONFIG")); //NOI18N
  342. //First do this to get outside ProjectManager.mutex()
  343. EventQueue.invokeLater(new Runnable() {
  344. public void run() {
  345. JComponent comp = ProgressHandleFactory.createProgressComponent(handle);
  346. JLabel lbl = ProgressHandleFactory.createMainLabelComponent(handle);
  347. JPanel pnl = new JPanel(new BorderLayout());
  348. pnl.add (lbl, BorderLayout.NORTH);
  349. pnl.add (comp, BorderLayout.SOUTH);
  350. String title = NbBundle.getMessage(ProjectConfigurationsHelper.class,
  351. "MSG_CHANGE_CONFIG"); //NOI18N
  352. JDialog dlg = new JDialog (WindowManager.getDefault().getMainWindow());
  353. dlg.setModal(true);
  354. dlg.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
  355. dlg.setTitle(title);
  356. dlg.getContentPane().setLayout(new BorderLayout());
  357. dlg.getContentPane().add(pnl, BorderLayout.CENTER);
  358. dlg.setLocationRelativeTo(dlg.getParent());
  359. RequestProcessor.Task task = p.getRequestProcessor().post(new ConfigurationChanger(handle, configuration, dlg));
  360. try {
  361. //50ms not noticable to the user - we can wait this long
  362. //before showing a dialog - simple projects will be fast.
  363. task.waitFinished(50);
  364. } catch (InterruptedException ex) {
  365. Exceptions.printStackTrace(ex);
  366. }
  367. if (!task.isFinished()) {
  368. dlg.pack();
  369. dlg.setVisible(true);
  370. }
  371. }
  372. });
  373. }
  374. private final class ConfigurationChanger extends WindowAdapter implements Runnable {
  375. private final ProgressHandle handle;
  376. private final ProjectConfiguration configuration;
  377. private final Dialog dlg;
  378. private volatile boolean done;
  379. ConfigurationChanger(ProgressHandle handle, ProjectConfiguration config, Dialog dlg) {
  380. this.configuration = config;
  381. this.handle = handle;
  382. this.dlg = dlg;
  383. handle.start();
  384. handle.switchToIndeterminate();
  385. dlg.addWindowListener(this);
  386. }
  387. @Override
  388. public void windowOpened(WindowEvent e) {
  389. //This can happen:
  390. //Task completes and tries to hide the dialog before it actually
  391. //gets on screen. So we also listen to the window and make sure
  392. //it doesn't show up *after* the task has completed
  393. if (done) {
  394. runOnEQ();
  395. }
  396. }
  397. public void run() {
  398. if (!EventQueue.isDispatchThread()) {
  399. try {
  400. runOffEQ();
  401. } finally {
  402. handle.finish();
  403. EventQueue.invokeLater(this);
  404. }
  405. done = true;
  406. } else {
  407. runOnEQ();
  408. }
  409. }
  410. private void runOnEQ() {
  411. dlg.setVisible(false);
  412. dlg.dispose();
  413. }
  414. private void runOffEQ() {
  415. final ProjectConfiguration oldAC = activeConfiguration;
  416. activeConfiguration = null;
  417. final EditableProperties ep = h.getProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH);
  418. ep.put(PROJ_PROP_CONFIGURATION_ACTIVE, (configuration == null ||
  419. configuration.equals(getDefaultConfiguration())) ? "" : configuration.getDisplayName()); //NOI18N
  420. try {
  421. ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Object>() {
  422. public Object run() {
  423. h.putProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH, ep);
  424. return null;
  425. }
  426. });
  427. ProjectManager.getDefault().saveProject(p);
  428. } catch (IOException ioe) {
  429. Exceptions.printStackTrace(ioe);
  430. } catch (MutexException me) {
  431. Exceptions.printStackTrace(me);
  432. }
  433. final ProjectConfiguration newAC = getActiveConfiguration();
  434. if ((oldAC != null) ? (!oldAC.equals(newAC)) : (newAC != null)) {
  435. psp.firePropertyChange(PROP_CONFIGURATION_ACTIVE, oldAC, newAC);
  436. }
  437. }
  438. }
  439. public void configurationXmlChanged(final AntProjectEvent ev) {
  440. }
  441. public synchronized void propertiesChanged(final AntProjectEvent ev) {
  442. if (psp == null) return;
  443. if (AntProjectHelper.PRIVATE_PROPERTIES_PATH.equals(ev.getPath())) {
  444. final ProjectConfiguration oldAC = activeConfiguration;
  445. activeConfiguration = null;
  446. final ProjectConfiguration newAC = getActiveConfiguration();
  447. if ((oldAC == null && newAC != null) || (oldAC != null && ! oldAC.equals(newAC))) {
  448. psp.firePropertyChange(PROP_CONFIGURATION_ACTIVE, oldAC, newAC);
  449. }
  450. } else if (AntProjectHelper.PROJECT_PROPERTIES_PATH.equals(ev.getPath())) {
  451. invalid = true;
  452. final TreeMap<String,ProjectConfiguration> old = configurations;
  453. final ProjectConfiguration oldCFs[]=old.values().toArray(new ProjectConfiguration[old.size()]);
  454. configurations = null;
  455. final ProjectConfiguration newCFs[] = getConfigurations(old).toArray(new ProjectConfiguration[0]);
  456. if (!Arrays.equals(oldCFs, newCFs)) {
  457. psp.firePropertyChange(PROP_CONFIGURATIONS, oldCFs, newCFs);
  458. }
  459. psp.firePropertyChange(PROJECT_PROPERTIES, null, getActiveConfiguration());
  460. }
  461. }
  462. public boolean hasCustomizer() {
  463. return true;
  464. }
  465. public void customize() {
  466. final J2MECustomizerProvider cp = p.getLookup().lookup(J2MECustomizerProvider.class);
  467. if (cp != null) SwingUtilities.invokeLater(new Runnable() {
  468. public void run() {
  469. cp.showCustomizer(true);
  470. }
  471. });
  472. }
  473. public boolean configurationsAffectAction(String command) {
  474. return false;
  475. }
  476. private static final class ConfigurationImpl implements ProjectConfiguration {
  477. private final String name;
  478. public ConfigurationImpl(String name) {
  479. this.name = name;
  480. }
  481. public String getDisplayName() {
  482. return name;
  483. }
  484. public boolean equals(final Object o) {
  485. if (! (o instanceof ConfigurationImpl))
  486. return false;
  487. final String name2 = ((ConfigurationImpl) o).getDisplayName();
  488. return (name != null) ? name.equals(name2) : name2 == null;
  489. }
  490. public int hashCode() {
  491. return (name != null) ? name.hashCode() : 0;
  492. }
  493. }
  494. }