0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.netbeans.api.debugger;
0043:
0044: import java.beans.Customizer;
0045: import java.beans.PropertyChangeEvent;
0046: import java.beans.PropertyChangeListener;
0047: import java.io.BufferedReader;
0048: import java.io.IOException;
0049: import java.io.InputStream;
0050: import java.io.InputStreamReader;
0051: import java.io.OutputStream;
0052: import java.io.PrintWriter;
0053: import java.lang.reflect.Array;
0054:
0055: import java.util.ArrayList;
0056: import java.util.Collection;
0057: import java.util.Collections;
0058: import java.util.HashMap;
0059: import java.util.HashSet;
0060: import java.util.Iterator;
0061: import java.util.List;
0062: import java.util.Map;
0063: import java.util.Set;
0064:
0065: import org.openide.ErrorManager;
0066: import org.openide.filesystems.FileLock;
0067: import org.openide.filesystems.FileSystem;
0068: import org.openide.filesystems.Repository;
0069: import org.openide.filesystems.FileObject;
0070: import org.openide.util.RequestProcessor;
0071:
0072: /**
0073: * Utility class hepls store properties.
0074: *
0075: * @author Jan Jancura
0076: */
0077: public abstract class Properties {
0078:
0079: private static Properties defaultProperties;
0080:
0081: /**
0082: * Returns shared instance of Properties class.
0083: *
0084: * @return shared instance of Properties class
0085: */
0086: public static synchronized Properties getDefault() {
0087: if (defaultProperties == null)
0088: defaultProperties = new PropertiesImpl();
0089: return defaultProperties;
0090: }
0091:
0092: /**
0093: * Reads String property from storage.
0094: *
0095: * @param propertyName a propertyName of property
0096: * @param defaultValue a default value to be used if property is not set
0097: * @return a current value of property
0098: */
0099: public abstract String getString(String propertyName,
0100: String defaultValue);
0101:
0102: /**
0103: * Sets a new value of property with given propertyName.
0104: *
0105: * @param propertyName a propertyName of property
0106: * @param value the new value of property
0107: */
0108: public abstract void setString(String propertyName, String value);
0109:
0110: /**
0111: * Reads int property from storage.
0112: *
0113: * @param propertyName a propertyName of property
0114: * @param defaultValue a default value to be used if property is not set
0115: * @return a current value of property
0116: */
0117: public abstract int getInt(String propertyName, int defaultValue);
0118:
0119: /**
0120: * Sets a new value of property with given propertyName.
0121: *
0122: * @param propertyName a propertyName of property
0123: * @param value the new value of property
0124: */
0125: public abstract void setInt(String propertyName, int value);
0126:
0127: /**
0128: * Reads char property from storage.
0129: *
0130: * @param propertyName a propertyName of property
0131: * @param defaultValue a default value to be used if property is not set
0132: * @return a current value of property
0133: */
0134: public abstract char getChar(String propertyName, char defaultValue);
0135:
0136: /**
0137: * Sets a new value of property with given propertyName.
0138: *
0139: * @param propertyName a propertyName of property
0140: * @param value the new value of property
0141: */
0142: public abstract void setChar(String propertyName, char value);
0143:
0144: /**
0145: * Reads float property from storage.
0146: *
0147: * @param propertyName a propertyName of property
0148: * @param defaultValue a default value to be used if property is not set
0149: * @return a current value of property
0150: */
0151: public abstract float getFloat(String propertyName,
0152: float defaultValue);
0153:
0154: /**
0155: * Sets a new value of property with given propertyName.
0156: *
0157: * @param propertyName a propertyName of property
0158: * @param value the new value of property
0159: */
0160: public abstract void setFloat(String propertyName, float value);
0161:
0162: /**
0163: * Reads long property from storage.
0164: *
0165: * @param propertyName a propertyName of property
0166: * @param defaultValue a default value to be used if property is not set
0167: * @return a current value of property
0168: */
0169: public abstract long getLong(String propertyName, long defaultValue);
0170:
0171: /**
0172: * Sets a new value of property with given propertyName.
0173: *
0174: * @param propertyName a propertyName of property
0175: * @param value the new value of property
0176: */
0177: public abstract void setLong(String propertyName, long value);
0178:
0179: /**
0180: * Reads double property from storage.
0181: *
0182: * @param propertyName a propertyName of property
0183: * @param defaultValue a default value to be used if property is not set
0184: * @return a current value of property
0185: */
0186: public abstract double getDouble(String propertyName,
0187: double defaultValue);
0188:
0189: /**
0190: * Sets a new value of property with given propertyName.
0191: *
0192: * @param propertyName a propertyName of property
0193: * @param value the new value of property
0194: */
0195: public abstract void setDouble(String propertyName, double value);
0196:
0197: /**
0198: * Reads boolean property from storage.
0199: *
0200: * @param propertyName a propertyName of property
0201: * @param defaultValue a default value to be used if property is not set
0202: * @return a current value of property
0203: */
0204: public abstract boolean getBoolean(String propertyName,
0205: boolean defaultValue);
0206:
0207: /**
0208: * Sets a new value of property with given propertyName.
0209: *
0210: * @param propertyName a propertyName of property
0211: * @param value the new value of property
0212: */
0213: public abstract void setBoolean(String propertyName, boolean value);
0214:
0215: /**
0216: * Reads byte property from storage.
0217: *
0218: * @param propertyName a propertyName of property
0219: * @param defaultValue a default value to be used if property is not set
0220: * @return a current value of property
0221: */
0222: public abstract byte getByte(String propertyName, byte defaultValue);
0223:
0224: /**
0225: * Sets a new value of property with given propertyName.
0226: *
0227: * @param propertyName a propertyName of property
0228: * @param value the new value of property
0229: */
0230: public abstract void setByte(String propertyName, byte value);
0231:
0232: /**
0233: * Reads short property from storage.
0234: *
0235: * @param propertyName a propertyName of property
0236: * @param defaultValue a default value to be used if property is not set
0237: * @return a current value of property
0238: */
0239: public abstract short getShort(String propertyName,
0240: short defaultValue);
0241:
0242: /**
0243: * Sets a new value of property with given propertyName.
0244: *
0245: * @param propertyName a propertyName of property
0246: * @param value the new value of property
0247: */
0248: public abstract void setShort(String propertyName, short value);
0249:
0250: /**
0251: * Reads Object property from storage.
0252: *
0253: * @param propertyName a propertyName of property
0254: * @param defaultValue a default value to be used if property is not set
0255: * @return a current value of property
0256: */
0257:
0258: public abstract Object getObject(String propertyName,
0259: Object defaultValue);
0260:
0261: /**
0262: * Sets a new value of property with given propertyName.
0263: *
0264: * @param propertyName a propertyName of property
0265: * @param value the new value of property
0266: */
0267: public abstract void setObject(String propertyName, Object value);
0268:
0269: /**
0270: * Reads array property from storage.
0271: *
0272: * @param propertyName a propertyName of property
0273: * @param defaultValue a default value to be used if property is not set
0274: * @return a current value of property
0275: */
0276: public abstract Object[] getArray(String propertyName,
0277: Object[] defaultValue);
0278:
0279: /**
0280: * Sets a new value of property with given propertyName.
0281: *
0282: * @param propertyName a propertyName of property
0283: * @param value the new value of property
0284: */
0285: public abstract void setArray(String propertyName, Object[] value);
0286:
0287: /**
0288: * Reads Collection property from storage.
0289: *
0290: * @param propertyName a propertyName of property
0291: * @param defaultValue a default value to be used if property is not set
0292: * @return a current value of property
0293: */
0294: public abstract Collection getCollection(String propertyName,
0295: Collection defaultValue);
0296:
0297: /**
0298: * Sets a new value of property with given propertyName.
0299: *
0300: * @param propertyName a propertyName of property
0301: * @param value the new value of property
0302: */
0303: public abstract void setCollection(String propertyName,
0304: Collection value);
0305:
0306: /**
0307: * Reads Map property from storage.
0308: *
0309: * @param propertyName a propertyName of property
0310: * @param defaultValue a default value to be used if property is not set
0311: * @return a current value of property
0312: */
0313: public abstract Map getMap(String propertyName, Map defaultValue);
0314:
0315: /**
0316: * Sets a new value of property with given propertyName.
0317: *
0318: * @param propertyName a propertyName of property
0319: * @param value the new value of property
0320: */
0321: public abstract void setMap(String propertyName, Map value);
0322:
0323: /**
0324: * Returns Properties instance for some "subfolder" in properties file.
0325: *
0326: * @param propertyName a subfolder name
0327: * @return a Properties instance for some "subfolder" in properties file
0328: */
0329: public abstract Properties getProperties(String propertyName);
0330:
0331: // innerclasses ............................................................
0332:
0333: /**
0334: * This class helps to store and read custom types using
0335: * {@link Properties#setObject} and {@link Properties#getObject} methods.
0336: * Implementations of this class should be stored in "META_INF\debugger"
0337: * folder.
0338: */
0339: public interface Reader {
0340:
0341: /**
0342: * Returns array of classNames supported by this reader.
0343: *
0344: * @return array of classNames supported by this reader
0345: */
0346: public String[] getSupportedClassNames();
0347:
0348: /**
0349: * Reads object with given className.
0350: *
0351: * @param className a name of class to be readed
0352: * @param properties a properties subfloder containing properties
0353: * for this object
0354: * @return a new instance of className class
0355: */
0356: public Object read(String className, Properties properties);
0357:
0358: /**
0359: * Writes given object to given properties subfolder.
0360: *
0361: * @param object a object to be saved
0362: * @param properties a properties subfolder to be used
0363: */
0364: public void write(Object object, Properties properties);
0365: }
0366:
0367: private final static class PrimitiveRegister {
0368:
0369: private HashMap properties = new HashMap();
0370: private boolean isInitialized = false;
0371:
0372: public String getProperty(String propertyName,
0373: String defaultValue) {
0374: synchronized (this ) {
0375: if (!isInitialized) {
0376: load();
0377: isInitialized = true;
0378: }
0379: String value = (String) properties.get(propertyName);
0380: if (value != null) {
0381: return value;
0382: }
0383: }
0384: return defaultValue;
0385: }
0386:
0387: public void setProperty(String propertyName, String value) {
0388: synchronized (this ) {
0389: if (!isInitialized) {
0390: load();
0391: isInitialized = true;
0392: }
0393: properties.put(propertyName, value);
0394: }
0395: save();
0396: }
0397:
0398: private synchronized void load() {
0399: BufferedReader br = null;
0400: try {
0401: FileObject fo = findSettings();
0402: InputStream is = fo.getInputStream();
0403: br = new BufferedReader(new InputStreamReader(is));
0404:
0405: String l = br.readLine();
0406: while (l != null) {
0407: int i = l.indexOf(':');
0408: if (i > 0)
0409: properties.put(l.substring(0, i), l
0410: .substring(i + 1));
0411: l = br.readLine();
0412: }
0413: br.close();
0414: } catch (IOException ex) {
0415: ErrorManager.getDefault().notify(ex);
0416: }
0417: }
0418:
0419: // currently waiting / running refresh task
0420: // there is at most one
0421: private RequestProcessor.Task task;
0422:
0423: private synchronized void save() {
0424: if (task == null) {
0425: task = new RequestProcessor(
0426: "Debugger Properties Save RP", 1)
0427: .create(new Runnable() {
0428: public void run() {
0429: saveIn();
0430: }
0431: });
0432: }
0433: task.schedule(4000);
0434: }
0435:
0436: private synchronized void saveIn() {
0437: PrintWriter pw = null;
0438: FileLock lock = null;
0439: try {
0440: FileObject fo = findSettings();
0441: lock = fo.lock();
0442: OutputStream os = fo.getOutputStream(lock);
0443: pw = new PrintWriter(os);
0444:
0445: Set s = properties.keySet();
0446: ArrayList l = new ArrayList(s);
0447: Collections.sort(l);
0448: int i, k = l.size();
0449: for (i = 0; i < k; i++) {
0450: String key = (String) l.get(i);
0451: Object value = properties.get(key);
0452: if (value != null) {
0453: // Do not write null values
0454: pw.println("" + key + ":" + value);
0455: }
0456: }
0457: pw.flush();
0458: } catch (IOException ex) {
0459: ErrorManager.getDefault().notify(
0460: ErrorManager.getDefault().annotate(ex,
0461: "Can not save debugger settings."));
0462: } finally {
0463: try {
0464: if (pw != null) {
0465: pw.close();
0466: }
0467: } finally {
0468: if (lock != null) {
0469: lock.releaseLock();
0470: }
0471: }
0472: }
0473: }
0474:
0475: private static FileObject findSettings() throws IOException {
0476: FileSystem fs = Repository.getDefault()
0477: .getDefaultFileSystem();
0478: FileObject r = fs.findResource("Services"); // NOI18N
0479: if (r == null) {
0480: r = fs.getRoot().createFolder("Services"); // NOI18N
0481: }
0482: FileObject fo = r.getFileObject(
0483: "org-netbeans-modules-debugger-Settings",
0484: "properties"); // NOI18N
0485: if (fo == null) {
0486: fo = r.createData(
0487: "org-netbeans-modules-debugger-Settings",
0488: "properties"); // NOI18N
0489: }
0490: return fo;
0491: }
0492: }
0493:
0494: // package-private because of tests
0495: static class PropertiesImpl extends Properties {
0496:
0497: private static final Object BAD_OBJECT = new Object();
0498: private static final String BAD_STRING = "";
0499: private static final Map BAD_MAP = new HashMap();
0500: private static final Collection BAD_COLLECTION = new ArrayList();
0501: private static final Object[] BAD_ARRAY = new Object[0];
0502:
0503: private List<? extends Reader> readersList;
0504: private HashMap<String, Reader> register;
0505:
0506: private PrimitiveRegister impl = new PrimitiveRegister();
0507:
0508: private void initReaders() {
0509: register = new HashMap<String, Reader>();
0510: readersList = DebuggerManager.getDebuggerManager().lookup(
0511: null, Reader.class);
0512: synchronized (readersList) {
0513: for (Reader r : readersList) {
0514: registerReader(r);
0515: }
0516: }
0517: ((Customizer) readersList)
0518: .addPropertyChangeListener(new PropertyChangeListener() {
0519: public void propertyChange(
0520: PropertyChangeEvent evt) {
0521: synchronized (PropertiesImpl.this ) {
0522: Set<Reader> registeredReaders = new HashSet<Reader>(
0523: register.values());
0524: synchronized (readersList) {
0525: for (Reader r : readersList) {
0526: if (!registeredReaders
0527: .remove(r)) {
0528: registerReader(r);
0529: }
0530: }
0531: }
0532: for (Reader r : registeredReaders) {
0533: unregisterReader(r);
0534: }
0535: }
0536: }
0537: });
0538: ((Customizer) readersList)
0539: .setObject(Lookup.NOTIFY_LOAD_FIRST);
0540: ((Customizer) readersList)
0541: .setObject(Lookup.NOTIFY_UNLOAD_LAST);
0542: }
0543:
0544: private void registerReader(Reader r) {
0545: //System.err.println("registerReader("+r+")");
0546: String[] ns = r.getSupportedClassNames();
0547: int j, jj = ns.length;
0548: for (j = 0; j < jj; j++) {
0549: register.put(ns[j], r);
0550: }
0551: }
0552:
0553: private void unregisterReader(Reader r) {
0554: //System.err.println("unregisterReader("+r+")");
0555: String[] ns = r.getSupportedClassNames();
0556: int j, jj = ns.length;
0557: for (j = 0; j < jj; j++) {
0558: register.remove(ns[j]);
0559: }
0560: }
0561:
0562: // Used from tests
0563: synchronized void addReader(Reader r) {
0564: if (register == null) {
0565: initReaders();
0566: }
0567: registerReader(r);
0568: }
0569:
0570: private synchronized Reader findReader(String typeID) {
0571: if (register == null) {
0572: initReaders();
0573: }
0574:
0575: Reader r = (Reader) register.get(typeID);
0576: if (r != null)
0577: return r;
0578:
0579: Class c = null;
0580: try {
0581: c = getClassLoader().loadClass(typeID);
0582: } catch (ClassNotFoundException e) {
0583: ErrorManager.getDefault().notify(e);
0584: return null;
0585: }
0586: while ((c != null) && (register.get(c.getName()) == null)) {
0587: c = c.getSuperclass();
0588: }
0589: if (c != null)
0590: r = (Reader) register.get(c.getName());
0591: return r;
0592: }
0593:
0594: // primitive properties ....................................................................................
0595:
0596: public String getString(String propertyName, String defaultValue) {
0597: String value = impl.getProperty(propertyName, null);
0598: if (value == null)
0599: return defaultValue;
0600: if (!value.startsWith("\"")) {
0601: ErrorManager.getDefault().log(
0602: "Can not read string " + value + ".");
0603: return defaultValue;
0604: }
0605: return value.substring(1, value.length() - 1);
0606: }
0607:
0608: public void setString(String propertyName, String value) {
0609: if (value != null) {
0610: impl.setProperty(propertyName, "\"" + value + "\"");
0611: } else {
0612: impl.setProperty(propertyName, value);
0613: }
0614: }
0615:
0616: public int getInt(String propertyName, int defaultValue) {
0617: String value = impl.getProperty(propertyName, null);
0618: if (value == null)
0619: return defaultValue;
0620: try {
0621: int val = Integer.parseInt(value);
0622: return val;
0623: } catch (NumberFormatException nfex) {
0624: return defaultValue;
0625: }
0626: }
0627:
0628: public void setInt(String propertyName, int value) {
0629: impl.setProperty(propertyName, Integer.toString(value));
0630: }
0631:
0632: public char getChar(String propertyName, char defaultValue) {
0633: String value = impl.getProperty(propertyName, null);
0634: if (value == null)
0635: return defaultValue;
0636: char val = value.charAt(0);
0637: return val;
0638: }
0639:
0640: public void setChar(String propertyName, char value) {
0641: impl.setProperty(propertyName, Character.toString(value));
0642: }
0643:
0644: public float getFloat(String propertyName, float defaultValue) {
0645: String value = impl.getProperty(propertyName, null);
0646: if (value == null)
0647: return defaultValue;
0648: try {
0649: float val = Float.parseFloat(value);
0650: return val;
0651: } catch (NumberFormatException nfex) {
0652: return defaultValue;
0653: }
0654: }
0655:
0656: public void setFloat(String propertyName, float value) {
0657: impl.setProperty(propertyName, Float.toString(value));
0658: }
0659:
0660: public long getLong(String propertyName, long defaultValue) {
0661: String value = impl.getProperty(propertyName, null);
0662: if (value == null)
0663: return defaultValue;
0664: try {
0665: long val = Long.parseLong(value);
0666: return val;
0667: } catch (NumberFormatException nfex) {
0668: return defaultValue;
0669: }
0670: }
0671:
0672: public void setLong(String propertyName, long value) {
0673: impl.setProperty(propertyName, Long.toString(value));
0674: }
0675:
0676: public double getDouble(String propertyName, double defaultValue) {
0677: String value = impl.getProperty(propertyName, null);
0678: if (value == null)
0679: return defaultValue;
0680: try {
0681: double val = Double.parseDouble(value);
0682: return val;
0683: } catch (NumberFormatException nfex) {
0684: return defaultValue;
0685: }
0686: }
0687:
0688: public void setDouble(String propertyName, double value) {
0689: impl.setProperty(propertyName, Double.toString(value));
0690: }
0691:
0692: public boolean getBoolean(String propertyName,
0693: boolean defaultValue) {
0694: String value = impl.getProperty(propertyName, null);
0695: if (value == null)
0696: return defaultValue;
0697: boolean val = value.equals("true");
0698: return val;
0699: }
0700:
0701: public void setBoolean(String propertyName, boolean value) {
0702: impl.setProperty(propertyName, value ? "true" : "false");
0703: }
0704:
0705: public byte getByte(String propertyName, byte defaultValue) {
0706: String value = impl.getProperty(propertyName, null);
0707: if (value == null)
0708: return defaultValue;
0709: try {
0710: byte val = Byte.parseByte(value);
0711: return val;
0712: } catch (NumberFormatException nfex) {
0713: return defaultValue;
0714: }
0715: }
0716:
0717: public void setByte(String propertyName, byte value) {
0718: impl.setProperty(propertyName, Byte.toString(value));
0719: }
0720:
0721: public short getShort(String propertyName, short defaultValue) {
0722: String value = impl.getProperty(propertyName, null);
0723: if (value == null)
0724: return defaultValue;
0725: try {
0726: short val = Short.parseShort(value);
0727: return val;
0728: } catch (NumberFormatException nfex) {
0729: return defaultValue;
0730: }
0731: }
0732:
0733: public void setShort(String propertyName, short value) {
0734: impl.setProperty(propertyName, Short.toString(value));
0735: }
0736:
0737: public Object getObject(String propertyName, Object defaultValue) {
0738: synchronized (impl) {
0739: String typeID = impl.getProperty(propertyName, null);
0740: if (typeID == null)
0741: return defaultValue;
0742: if (typeID.equals("# null"))
0743: return null;
0744: if (!typeID.startsWith("# ")) {
0745: if (typeID.startsWith("\"")) {
0746: String s = getString(propertyName, BAD_STRING);
0747: if (s == BAD_STRING)
0748: return defaultValue;
0749: return s;
0750: }
0751: ErrorManager
0752: .getDefault()
0753: .log(
0754: "Can not read object "
0755: + typeID
0756: + ". No reader registered for type "
0757: + typeID + ".");
0758: return defaultValue;
0759: }
0760: typeID = typeID.substring(2);
0761: Class c = null;
0762: try {
0763: c = Class.forName(typeID);
0764: } catch (ClassNotFoundException e) {
0765: }
0766: if (c != null) {
0767: if (Map.class.isAssignableFrom(c)) {
0768: Map m = getMap(propertyName, BAD_MAP);
0769: if (m == BAD_MAP)
0770: return defaultValue;
0771: return m;
0772: }
0773: if (Object[].class.isAssignableFrom(c)) {
0774: Object[] os = getArray(propertyName, BAD_ARRAY);
0775: if (os == BAD_ARRAY)
0776: return defaultValue;
0777: return os;
0778: }
0779: if (Collection.class.isAssignableFrom(c)) {
0780: Collection co = getCollection(propertyName,
0781: BAD_COLLECTION);
0782: if (co == BAD_COLLECTION)
0783: return defaultValue;
0784: return co;
0785: }
0786: }
0787: Reader r = findReader(typeID);
0788: if (r == null) {
0789: ErrorManager.getDefault().log(
0790: "Can not read object. No reader registered for type "
0791: + typeID + ".");
0792: return defaultValue;
0793: }
0794: return r.read(typeID, getProperties(propertyName));
0795: }
0796: }
0797:
0798: public void setObject(String propertyName, Object value) {
0799: synchronized (impl) {
0800: if (value == null) {
0801: impl.setProperty(propertyName, "# null");
0802: return;
0803: }
0804: if (value instanceof String) {
0805: setString(propertyName, (String) value);
0806: return;
0807: }
0808: if (value instanceof Map) {
0809: setMap(propertyName, (Map) value);
0810: return;
0811: }
0812: if (value instanceof Collection) {
0813: setCollection(propertyName, (Collection) value);
0814: return;
0815: }
0816: if (value instanceof Object[]) {
0817: setArray(propertyName, (Object[]) value);
0818: return;
0819: }
0820:
0821: // find register
0822: Reader r = findReader(value.getClass().getName());
0823: if (r == null) {
0824: ErrorManager.getDefault().log(
0825: "Can not write object " + value);
0826: return;
0827: }
0828:
0829: // write
0830: r.write(value, getProperties(propertyName));
0831: impl.setProperty(propertyName, "# "
0832: + value.getClass().getName());
0833: }
0834: }
0835:
0836: public Object[] getArray(String propertyName,
0837: Object[] defaultValue) {
0838: synchronized (impl) {
0839: String arrayType = impl.getProperty(propertyName
0840: + ".array_type", null);
0841: Properties p = getProperties(propertyName);
0842: int l = p.getInt("length", -1);
0843: if (l < 0)
0844: return defaultValue;
0845: Object[] os = null;
0846: try {
0847: os = (Object[]) Array.newInstance(getClassLoader()
0848: .loadClass(arrayType), l);
0849: } catch (ClassNotFoundException ex) {
0850: ErrorManager.getDefault().notify(ex);
0851: os = new Object[l];
0852: }
0853: for (int i = 0; i < l; i++) {
0854: Object o = p.getObject("" + i, BAD_OBJECT);
0855: if (o == BAD_OBJECT)
0856: return defaultValue;
0857: os[i] = o;
0858: }
0859: return os;
0860: }
0861: }
0862:
0863: public void setArray(String propertyName, Object[] value) {
0864: synchronized (impl) {
0865: impl.setProperty(propertyName, "# array");
0866: impl.setProperty(propertyName + ".array_type", value
0867: .getClass().getComponentType().getName());
0868: Properties p = getProperties(propertyName);
0869: int i, k = value.length;
0870: p.setInt("length", k);
0871: for (i = 0; i < k; i++)
0872: p.setObject("" + i, value[i]);
0873: }
0874: }
0875:
0876: public Collection getCollection(String propertyName,
0877: Collection defaultValue) {
0878: synchronized (impl) {
0879: String typeID = impl.getProperty(propertyName, null);
0880: if (typeID == null)
0881: return defaultValue;
0882: if (!typeID.startsWith("# "))
0883: return defaultValue;
0884: Collection c = null;
0885: try {
0886: c = (Collection) Class.forName(typeID.substring(2))
0887: .newInstance();
0888: } catch (ClassNotFoundException ex) {
0889: System.err.println(ex.getLocalizedMessage());
0890: ErrorManager.getDefault().log(
0891: ex.getLocalizedMessage());
0892: ErrorManager.getDefault().notify(ex);
0893: return defaultValue;
0894: } catch (InstantiationException ex) {
0895: System.err.println(ex.getLocalizedMessage());
0896: ErrorManager.getDefault().log(
0897: ex.getLocalizedMessage());
0898: ErrorManager.getDefault().notify(ex);
0899: return defaultValue;
0900: } catch (IllegalAccessException ex) {
0901: System.err.println(ex.getLocalizedMessage());
0902: ErrorManager.getDefault().log(
0903: ex.getLocalizedMessage());
0904: ErrorManager.getDefault().notify(ex);
0905: return defaultValue;
0906: }
0907: Properties p = getProperties(propertyName);
0908: int i, k = p.getInt("length", 0);
0909: for (i = 0; i < k; i++) {
0910: Object o = p.getObject("" + i, BAD_OBJECT);
0911: if (o == BAD_OBJECT)
0912: return defaultValue;
0913: c.add(o);
0914: }
0915: return c;
0916: }
0917: }
0918:
0919: public void setCollection(String propertyName, Collection value) {
0920: synchronized (impl) {
0921: if (value == null) {
0922: impl.setProperty(propertyName, null);
0923: }
0924: impl.setProperty(propertyName, "# "
0925: + value.getClass().getName());
0926: Properties p = getProperties(propertyName);
0927: Iterator it = value.iterator();
0928: int i = 0;
0929: p.setInt("length", value.size());
0930: while (it.hasNext()) {
0931: p.setObject("" + i, it.next());
0932: i++;
0933: }
0934: }
0935: }
0936:
0937: public Map getMap(String propertyName, Map defaultValue) {
0938: synchronized (impl) {
0939: String typeID = impl.getProperty(propertyName, null);
0940: if (typeID == null)
0941: return defaultValue;
0942: if (!typeID.startsWith("# "))
0943: return defaultValue;
0944: Map m = null;
0945: try {
0946: m = (Map) Class.forName(typeID.substring(2))
0947: .newInstance();
0948: } catch (ClassNotFoundException ex) {
0949: ErrorManager.getDefault().log(
0950: ex.getLocalizedMessage());
0951: return defaultValue;
0952: } catch (InstantiationException ex) {
0953: ErrorManager.getDefault().log(
0954: ex.getLocalizedMessage());
0955: return defaultValue;
0956: } catch (IllegalAccessException ex) {
0957: ErrorManager.getDefault().log(
0958: ex.getLocalizedMessage());
0959: return defaultValue;
0960: }
0961: Properties p = getProperties(propertyName);
0962: int i, k = p.getInt("length", 0);
0963: for (i = 0; i < k; i++) {
0964: Object key = p.getObject("" + i + "-key",
0965: BAD_OBJECT);
0966: if (key == BAD_OBJECT)
0967: return defaultValue;
0968: Object value = p.getObject("" + i + "-value",
0969: BAD_OBJECT);
0970: if (value == BAD_OBJECT)
0971: return defaultValue;
0972: m.put(key, value);
0973: }
0974: return m;
0975: }
0976: }
0977:
0978: public void setMap(String propertyName, Map value) {
0979: synchronized (impl) {
0980: if (value == null) {
0981: impl.setProperty(propertyName, null);
0982: }
0983: impl.setProperty(propertyName, "# "
0984: + value.getClass().getName());
0985: Properties p = getProperties(propertyName);
0986: Iterator it = value.keySet().iterator();
0987: int i = 0;
0988: p.setInt("length", value.size());
0989: while (it.hasNext()) {
0990: Object o = it.next();
0991: p.setObject("" + i + "-key", o);
0992: p.setObject("" + i + "-value", value.get(o));
0993: i++;
0994: }
0995: }
0996: }
0997:
0998: public Properties getProperties(String propertyName) {
0999: return new DelegatingProperties(this , propertyName);
1000: }
1001:
1002: private static ClassLoader classLoader;
1003:
1004: private static ClassLoader getClassLoader() {
1005: if (classLoader == null)
1006: //Thread.currentThread ().getContextClassLoader ();
1007: classLoader = (ClassLoader) org.openide.util.Lookup
1008: .getDefault().lookup(ClassLoader.class);
1009: return classLoader;
1010: }
1011: }
1012:
1013: private static class DelegatingProperties extends Properties {
1014:
1015: private Properties delegatingProperties;
1016: private String root;
1017:
1018: DelegatingProperties(Properties properties, String root) {
1019: delegatingProperties = properties;
1020: this .root = root;
1021: }
1022:
1023: public String getString(String propertyName, String defaultValue) {
1024: return delegatingProperties.getString(root + '.'
1025: + propertyName, defaultValue);
1026: }
1027:
1028: public void setString(String propertyName, String value) {
1029: delegatingProperties.setString(root + '.' + propertyName,
1030: value);
1031: }
1032:
1033: public int getInt(String propertyName, int defaultValue) {
1034: return delegatingProperties.getInt(root + '.'
1035: + propertyName, defaultValue);
1036: }
1037:
1038: public void setInt(String propertyName, int value) {
1039: delegatingProperties.setInt(root + '.' + propertyName,
1040: value);
1041: }
1042:
1043: public byte getByte(String propertyName, byte defaultValue) {
1044: return delegatingProperties.getByte(root + '.'
1045: + propertyName, defaultValue);
1046: }
1047:
1048: public void setByte(String propertyName, byte value) {
1049: delegatingProperties.setByte(root + '.' + propertyName,
1050: value);
1051: }
1052:
1053: public char getChar(String propertyName, char defaultValue) {
1054: return delegatingProperties.getChar(root + '.'
1055: + propertyName, defaultValue);
1056: }
1057:
1058: public void setChar(String propertyName, char value) {
1059: delegatingProperties.setChar(root + '.' + propertyName,
1060: value);
1061: }
1062:
1063: public boolean getBoolean(String propertyName,
1064: boolean defaultValue) {
1065: return delegatingProperties.getBoolean(root + '.'
1066: + propertyName, defaultValue);
1067: }
1068:
1069: public void setBoolean(String propertyName, boolean value) {
1070: delegatingProperties.setBoolean(root + '.' + propertyName,
1071: value);
1072: }
1073:
1074: public short getShort(String propertyName, short defaultValue) {
1075: return delegatingProperties.getShort(root + '.'
1076: + propertyName, defaultValue);
1077: }
1078:
1079: public void setShort(String propertyName, short value) {
1080: delegatingProperties.setShort(root + '.' + propertyName,
1081: value);
1082: }
1083:
1084: public long getLong(String propertyName, long defaultValue) {
1085: return delegatingProperties.getLong(root + '.'
1086: + propertyName, defaultValue);
1087: }
1088:
1089: public void setLong(String propertyName, long value) {
1090: delegatingProperties.setLong(root + '.' + propertyName,
1091: value);
1092: }
1093:
1094: public double getDouble(String propertyName, double defaultValue) {
1095: return delegatingProperties.getDouble(root + '.'
1096: + propertyName, defaultValue);
1097: }
1098:
1099: public void setDouble(String propertyName, double value) {
1100: delegatingProperties.setDouble(root + '.' + propertyName,
1101: value);
1102: }
1103:
1104: public float getFloat(String propertyName, float defaultValue) {
1105: return delegatingProperties.getFloat(root + '.'
1106: + propertyName, defaultValue);
1107: }
1108:
1109: public void setFloat(String propertyName, float value) {
1110: delegatingProperties.setFloat(root + '.' + propertyName,
1111: value);
1112: }
1113:
1114: public Object getObject(String propertyName, Object defaultValue) {
1115: return delegatingProperties.getObject(root + '.'
1116: + propertyName, defaultValue);
1117: }
1118:
1119: public void setObject(String propertyName, Object value) {
1120: delegatingProperties.setObject(root + '.' + propertyName,
1121: value);
1122: }
1123:
1124: public Object[] getArray(String propertyName,
1125: Object[] defaultValue) {
1126: return delegatingProperties.getArray(root + '.'
1127: + propertyName, defaultValue);
1128: }
1129:
1130: public void setArray(String propertyName, Object[] value) {
1131: delegatingProperties.setArray(root + '.' + propertyName,
1132: value);
1133: }
1134:
1135: public Collection getCollection(String propertyName,
1136: Collection defaultValue) {
1137: return delegatingProperties.getCollection(root + '.'
1138: + propertyName, defaultValue);
1139: }
1140:
1141: public void setCollection(String propertyName, Collection value) {
1142: delegatingProperties.setCollection(root + '.'
1143: + propertyName, value);
1144: }
1145:
1146: public Map getMap(String propertyName, Map defaultValue) {
1147: return delegatingProperties.getMap(root + '.'
1148: + propertyName, defaultValue);
1149: }
1150:
1151: public void setMap(String propertyName, Map value) {
1152: delegatingProperties.setMap(root + '.' + propertyName,
1153: value);
1154: }
1155:
1156: public Properties getProperties(String propertyName) {
1157: return new DelegatingProperties(delegatingProperties, root
1158: + '.' + propertyName);
1159: }
1160: }
1161: }
|