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.apache.tools.ant.module;
043:
044: import java.beans.PropertyChangeListener;
045: import java.beans.PropertyChangeSupport;
046: import java.io.File;
047: import java.util.ArrayList;
048: import java.util.Arrays;
049: import java.util.HashMap;
050: import java.util.List;
051: import java.util.Map;
052: import java.util.SortedMap;
053: import java.util.TreeMap;
054: import java.util.logging.Logger;
055: import java.util.prefs.Preferences;
056: import java.util.regex.Pattern;
057: import org.apache.tools.ant.module.api.IntrospectedInfo;
058: import org.apache.tools.ant.module.bridge.AntBridge;
059: import org.apache.tools.ant.module.spi.AntEvent;
060: import org.apache.tools.ant.module.spi.AutomaticExtraClasspathProvider;
061: import org.openide.ErrorManager;
062: import org.openide.modules.InstalledFileLocator;
063: import org.openide.util.Lookup;
064: import org.openide.util.LookupEvent;
065: import org.openide.util.LookupListener;
066: import org.openide.util.NbPreferences;
067:
068: public class AntSettings {
069:
070: private static final String PROP_VERBOSITY = "verbosity"; // NOI18N
071: private static final String PROP_PROPERTIES = "properties"; // NOI18N
072: private static final String PROP_SAVE_ALL = "saveAll"; // NOI18N
073: private static final String PROP_CUSTOM_DEFS = "customDefs"; // NOI18N
074: public static final String PROP_ANT_HOME = "antHome"; // NOI18N
075: public static final String PROP_EXTRA_CLASSPATH = "extraClasspath"; // NOI18N
076: public static final String PROP_AUTOMATIC_EXTRA_CLASSPATH = "automaticExtraClasspath"; // NOI18N
077: private static final String PROP_AUTO_CLOSE_TABS = "autoCloseTabs"; // NOI18N
078: private static final String PROP_ALWAYS_SHOW_OUTPUT = "alwaysShowOutput"; // NOI18N
079:
080: private AntSettings() {
081: }
082:
083: private static Preferences prefs() {
084: return NbPreferences.forModule(AntSettings.class);
085: }
086:
087: public static int getVerbosity() {
088: return prefs().getInt(PROP_VERBOSITY, AntEvent.LOG_INFO);
089: }
090:
091: public static void setVerbosity(int v) {
092: prefs().putInt(PROP_VERBOSITY, v);
093: }
094:
095: public static Map<String, String> getProperties() {
096: Map<String, String> p = new HashMap<String, String>();
097: // Enable hyperlinking for Jikes by default:
098: for (String pair : prefs().get(PROP_PROPERTIES,
099: "build.compiler.emacs=true").split("\n")) { // NOI18N
100: String[] nameval = pair.split("=", 2); // NOI18N
101: if (nameval.length != 2) {
102: Logger.getLogger(AntSettings.class.getName()).warning(
103: "Unexpected name=value pair: '" + pair + "'");
104: continue;
105: }
106: p.put(nameval[0], nameval[1]);
107: }
108: return p;
109: }
110:
111: public static void setProperties(Map<String, String> p) {
112: if (!(p instanceof SortedMap)) {
113: p = new TreeMap<String, String>(p);
114: }
115: StringBuilder b = new StringBuilder();
116: for (Map.Entry<String, String> pair : p.entrySet()) {
117: if (b.length() > 0) {
118: b.append('\n');
119: }
120: b.append(pair.getKey());
121: b.append('=');
122: b.append(pair.getValue());
123: }
124: prefs().put(PROP_PROPERTIES, b.toString());
125: }
126:
127: public static boolean getSaveAll() {
128: return prefs().getBoolean(PROP_SAVE_ALL, true);
129: }
130:
131: public static void setSaveAll(boolean sa) {
132: prefs().putBoolean(PROP_SAVE_ALL, sa);
133: }
134:
135: private static IntrospectedInfo customDefs;
136: static {
137: new IntrospectedInfo(); // trigger IntrospectedInfo static block
138: }
139:
140: public static synchronized IntrospectedInfo getCustomDefs() {
141: if (customDefs == null) {
142: customDefs = IntrospectedInfoSerializer.instance
143: .load(prefs().node(PROP_CUSTOM_DEFS));
144: }
145: return customDefs;
146: }
147:
148: public static synchronized void setCustomDefs(IntrospectedInfo ii) {
149: IntrospectedInfoSerializer.instance.store(prefs().node(
150: PROP_CUSTOM_DEFS), ii);
151: customDefs = ii;
152: }
153:
154: private static String antVersion;
155:
156: // #14993: read-only property for the version of Ant
157: public static String getAntVersion() {
158: if (antVersion == null) {
159: antVersion = AntBridge.getInterface().getAntVersion();
160: }
161: return antVersion;
162: }
163:
164: /**
165: * Transient value of ${ant.home} unless otherwise set.
166: * @see "#43522"
167: */
168: private static File defaultAntHome = null;
169:
170: private static synchronized File getDefaultAntHome() {
171: if (defaultAntHome == null) {
172: File antJar = InstalledFileLocator.getDefault().locate(
173: "ant/lib/ant.jar", "org.apache.tools.ant.module",
174: false); // NOI18N
175: if (antJar == null) {
176: return null;
177: }
178: defaultAntHome = antJar.getParentFile().getParentFile();
179: if (AntModule.err.isLoggable(ErrorManager.INFORMATIONAL)) {
180: AntModule.err.log("getDefaultAntHome: "
181: + defaultAntHome);
182: }
183: }
184: assert defaultAntHome != null;
185: return defaultAntHome;
186: }
187:
188: /**
189: * Get the Ant installation to use.
190: * Might be null!
191: */
192: public static File getAntHome() {
193: String h = prefs().get(PROP_ANT_HOME, null);
194: if (AntModule.err.isLoggable(ErrorManager.INFORMATIONAL)) {
195: AntModule.err.log("getAntHomeWithDefault: antHome=" + h);
196: }
197: if (h != null) {
198: return new File(h);
199: } else {
200: // Not explicitly configured. Check default.
201: return getDefaultAntHome();
202: }
203: }
204:
205: public static void setAntHome(File f) {
206: if (f != null && f.equals(getDefaultAntHome())) {
207: f = null;
208: }
209: if (AntModule.err.isLoggable(ErrorManager.INFORMATIONAL)) {
210: AntModule.err.log("setAntHome: " + f);
211: }
212: if (f != null) {
213: prefs().put(PROP_ANT_HOME, f.getAbsolutePath());
214: } else {
215: prefs().remove(PROP_ANT_HOME);
216: }
217: antVersion = null;
218: firePropertyChange(PROP_ANT_HOME);
219: }
220:
221: public static List<File> getExtraClasspath() {
222: // XXX could perhaps populate with xerces.jar:dom-ranges.jar
223: // However currently there is no sure way to get the "good" Xerces
224: // from libs/xerces (rather than the messed-up one from xml/tax)
225: // without hardcoding the JAR name, which seems unwise since it is
226: // definitely subject to change.
227: List<File> files = new ArrayList<File>();
228: for (String f : prefs().get(PROP_EXTRA_CLASSPATH, "").split(
229: Pattern.quote(File.pathSeparator))) {
230: files.add(new File(f));
231: }
232: return files;
233: }
234:
235: public static void setExtraClasspath(List<File> p) {
236: StringBuilder b = new StringBuilder();
237: for (File f : p) {
238: if (b.length() > 0) {
239: b.append(File.pathSeparatorChar);
240: }
241: b.append(f);
242: }
243: prefs().put(PROP_EXTRA_CLASSPATH, b.toString());
244: firePropertyChange(PROP_EXTRA_CLASSPATH);
245: }
246:
247: private static List<File> defAECP = null;
248: private static Lookup.Result<AutomaticExtraClasspathProvider> aecpResult = null;
249:
250: public static synchronized List<File> getAutomaticExtraClasspath() {
251: if (aecpResult == null) {
252: aecpResult = Lookup.getDefault().lookupResult(
253: AutomaticExtraClasspathProvider.class);
254: aecpResult.addLookupListener(new LookupListener() {
255: public void resultChanged(LookupEvent ev) {
256: defAECP = null;
257: firePropertyChange(PROP_AUTOMATIC_EXTRA_CLASSPATH);
258: }
259: });
260: }
261: if (defAECP == null) {
262: defAECP = new ArrayList<File>();
263: for (AutomaticExtraClasspathProvider provider : aecpResult
264: .allInstances()) {
265: defAECP.addAll(Arrays.asList(provider
266: .getClasspathItems()));
267: }
268: }
269: return defAECP;
270: }
271:
272: public static boolean getAutoCloseTabs() {
273: return prefs()
274: .getBoolean(PROP_AUTO_CLOSE_TABS, /*#47753*/true);
275: }
276:
277: public static void setAutoCloseTabs(boolean b) {
278: prefs().putBoolean(PROP_AUTO_CLOSE_TABS, b);
279: }
280:
281: public static boolean getAlwaysShowOutput() {
282: return prefs().getBoolean(PROP_ALWAYS_SHOW_OUTPUT, /* #87801 */
283: false);
284: }
285:
286: public static void setAlwaysShowOutput(boolean b) {
287: prefs().putBoolean(PROP_ALWAYS_SHOW_OUTPUT, b);
288: }
289:
290: private static final PropertyChangeSupport pcs = new PropertyChangeSupport(
291: AntSettings.class);
292:
293: public static void addPropertyChangeListener(
294: PropertyChangeListener l) {
295: pcs.addPropertyChangeListener(l);
296: }
297:
298: public static void removePropertyChangeListener(
299: PropertyChangeListener l) {
300: pcs.removePropertyChangeListener(l);
301: }
302:
303: private static void firePropertyChange(String prop) {
304: pcs.firePropertyChange(prop, null, null);
305: }
306:
307: public static abstract class IntrospectedInfoSerializer {
308: public static IntrospectedInfoSerializer instance;
309:
310: public abstract IntrospectedInfo load(Preferences node);
311:
312: public abstract void store(Preferences node,
313: IntrospectedInfo info);
314: }
315:
316: }
|