001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.midp.util;
028:
029: import java.util.Vector;
030: import java.util.Enumeration;
031:
032: /**
033: * The <code>Properties</code> class represents a persistent set of
034: * properties. Each key and its corresponding value in
035: * the property list is a string.
036: * <p>
037: */
038: public class Properties {
039: /** An appropriate initial size for storage vectors (10). */
040: private static int INITIAL_SIZE = 10;
041:
042: /**
043: * The initial properties as series of key-value pairs. This array will be
044: * used until a property is added, set, or removed.
045: * <p>
046: * The Java installer adds properties, also when a system MIDlet is
047: * run with arguments, the arguments are added to properties.
048: * 99.99% of the time, when running a downloaded MIDlet properties are
049: * not added the is no need to load the vectors.
050: */
051: private String[] initProps;
052:
053: /** A vector of property keys. */
054: private Vector keys;
055: /** A vector of property values. */
056: private Vector vals;
057:
058: /**
059: * Constructor - creates an empty property list.
060: */
061: public Properties() {
062: keys = new Vector(INITIAL_SIZE);
063: vals = new Vector(INITIAL_SIZE);
064: }
065:
066: /**
067: * Constructor - creates an populated property list.
068: *
069: * @param propertyStrings an array of Strings 2 per property, will be
070: * filled in with a pair pattern of key and value, this exact array
071: * will be used for property lookup (the array will not be changed).
072: * No other allocation will be done until the array is changed and at
073: * that time the initial property array will be released.
074: */
075: public Properties(String[] propertyStrings) {
076: initProps = propertyStrings;
077: }
078:
079: /**
080: * Convert the init property String array to vectors for changing
081: * properties.
082: */
083: private void convertInitPropsToVectors() {
084: int numberOfProps;
085:
086: numberOfProps = initProps.length / 2;
087:
088: keys = new Vector(numberOfProps + INITIAL_SIZE);
089: vals = new Vector(numberOfProps + INITIAL_SIZE);
090:
091: for (int i = 0; i < initProps.length; i += 2) {
092: keys.addElement(initProps[i]);
093: vals.addElement(initProps[i + 1]);
094: }
095:
096: // The initial properties are no longer needed.
097: initProps = null;
098: }
099:
100: /**
101: * Store multiple key:value pair. Provided for parallelism with the
102: * <tt>getProperty</tt> method. Enforces use of strings for
103: * property keys and values.
104: *
105: * @param key the key to be placed into this property list.
106: * @param value the value corresponding to <tt>key</tt>.
107: * @see #getProperty
108: */
109: public synchronized void addProperty(String key, String value) {
110: if (keys == null) {
111: convertInitPropsToVectors();
112: }
113:
114: keys.addElement(key);
115: vals.addElement(value);
116:
117: return;
118: }
119:
120: /**
121: * Store a single key:value pair. Provided for parallelism with the
122: * <tt>getProperty</tt> method. Enforces use of strings for
123: * property keys and values. If a key already exists in storage,
124: * the value corresponding to that key will be replaced and returned.
125: *
126: * @param key the key to be placed into this property list.
127: * @param value the value corresponding to <tt>key</tt>.
128: * @return if the new property value replaces an existing one, the old
129: * value is returned. otherwise, null is returned.
130: * @see #getProperty
131: * @see #removeProperty
132: */
133: public synchronized String setProperty(String key, String value) {
134: int idx;
135: String rv = null;
136:
137: if (keys == null) {
138: convertInitPropsToVectors();
139: }
140:
141: idx = keys.indexOf(key);
142:
143: if (idx == -1) { // If I don't have this, add it and return null
144: keys.addElement(key);
145: vals.addElement(value);
146: } else { // Else replace it and return the old one.
147: rv = (String) vals.elementAt(idx);
148: vals.setElementAt(value, idx);
149: }
150:
151: return rv;
152: }
153:
154: /**
155: * Store a single key:value pair.
156: *
157: * This method is very similar to setproperty() except with a difference
158: * that the keys are stored in case-insensitive manner. This is needed in
159: * certain situations like HTTP header names.
160: *
161: *
162: * @param key the key to be placed into this property list.
163: * @param value the value corresponding to <tt>key</tt>.
164: * @return if the new property value replaces an existing one, the old
165: * value is returned. otherwise, null is returned.
166: * @see #getProperty
167: * @see #removeProperty
168: */
169: public synchronized String setPropertyIgnoreCase(String key,
170: String value) {
171: int idx = -1;
172: String rv = null;
173:
174: if (keys == null) {
175: convertInitPropsToVectors();
176: }
177:
178: for (int count = 0; count < keys.size(); count++) {
179: if (((String) keys.elementAt(count)).equalsIgnoreCase(key)) {
180: idx = count;
181: }
182: }
183:
184: if (idx == -1) { // If I don't have this, add it and return null
185: keys.addElement(key);
186: vals.addElement(value);
187: } else { // Else replace it and return the old one.
188: rv = (String) vals.elementAt(idx);
189: vals.setElementAt(value, idx);
190: /*
191: * Also replace the key at idx in case there is change in case
192: * for the key
193: */
194: keys.setElementAt(key, idx);
195: }
196:
197: return rv;
198: }
199:
200: /**
201: * Replace the value of the property at the given index.
202: *
203: * @param index 0 based index of a property
204: * @param value the new value for the property at <tt>index</tt>.
205: *
206: * @return previous value
207: *
208: * @exception IndexOutOfBoundsException if the index is out of bounds
209: */
210: public synchronized String setPropertyAt(int index, String value) {
211: String rv;
212:
213: if (keys == null) {
214: convertInitPropsToVectors();
215: }
216:
217: rv = (String) vals.elementAt(index);
218:
219: vals.setElementAt(value, index);
220:
221: return rv;
222: }
223:
224: /**
225: * Searches for the property with the specified key in this property list.
226: * The method returns <code>null</code> if the property is not found.
227: *
228: * @param key the property key.
229: * @return the value in this property list with the specified key value.
230: * @exception NullPointerException is thrown if key is <code>null</code>.
231: * @see #setProperty
232: * @see #removeProperty
233: */
234: public String getProperty(String key) {
235: String rv = null;
236:
237: if (key == null) {
238: throw new NullPointerException();
239: }
240:
241: if (keys == null) {
242: for (int i = 0; i < initProps.length; i += 2) {
243: if (initProps[i].equals(key)) {
244: rv = initProps[i + 1];
245: break;
246: }
247: }
248: } else {
249: int idx = keys.indexOf(key);
250: if (idx > -1) {
251: rv = (String) vals.elementAt(idx);
252: }
253: }
254:
255: return rv;
256: }
257:
258: /**
259: * This method is very similar to getproperty() except with a difference
260: * that the keys are searched in case-insensitive manner. This is needed in
261: * certain situations like HTTP header names.
262: *
263: * @param key the property key.
264: * @return the value in this property list with the specified key value.
265: * @exception NullPointerException is thrown if key is <code>null</code>.
266: * @see #setProperty
267: * @see #removeProperty
268: */
269: public String getPropertyIgnoreCase(String key) {
270: String rv = null;
271:
272: if (key == null) {
273: throw new NullPointerException();
274: }
275:
276: if (keys == null) {
277: for (int i = 0; i < initProps.length; i += 2) {
278: if (initProps[i].equalsIgnoreCase(key)) {
279: rv = initProps[i + 1];
280: break;
281: }
282: }
283: } else {
284: int idx = -1;
285: for (int count = 0; count < keys.size(); count++) {
286: if (((String) keys.elementAt(count))
287: .equalsIgnoreCase(key)) {
288: idx = count;
289: }
290: }
291: if (idx > -1) {
292: rv = (String) vals.elementAt(idx);
293: }
294: }
295:
296: return rv;
297: }
298:
299: /**
300: * Gets a property value by index. Used by the JadWriter as part of the
301: * JAD Tool.
302: *
303: * @param index 0 based index of a property
304: * @return the value of the property with the specified index.
305: * @exception ArrayIndexOutOfBoundsException
306: * if an invalid index was given.
307: */
308: public String getValueAt(int index) {
309: if (keys == null) {
310: return initProps[(index * 2) + 1];
311: }
312:
313: return (String) vals.elementAt(index);
314: }
315:
316: /**
317: * Gets a property key by index. Used by the JadWriter as part of the
318: * JAD Tool.
319: *
320: * @param index 0 based index of a property
321: * @return the key of the property with the specified index.
322: * @exception ArrayIndexOutOfBoundsException
323: * if an invalid index was given.
324: */
325: public String getKeyAt(int index) {
326: if (keys == null) {
327: return initProps[index * 2];
328: }
329:
330: return (String) keys.elementAt(index);
331: }
332:
333: /**
334: * Gets the number of properties.
335: *
336: * @return number of properties
337: */
338: public int size() {
339: if (keys == null) {
340: return initProps.length / 2;
341: }
342:
343: return keys.size();
344: }
345:
346: /**
347: * Removes a property (key:value pair) from the property
348: * list based on the key string.
349: *
350: * @param key the key to be removed from the property list.
351: * @return the element associated with the key.
352: * @see #setProperty
353: * @see #getProperty
354: */
355: public synchronized String removeProperty(String key) {
356: int idx;
357: String rv = null;
358:
359: if (keys == null) {
360: convertInitPropsToVectors();
361: }
362:
363: idx = keys.indexOf(key);
364: if (idx > -1) {
365: rv = (String) vals.elementAt(idx);
366: keys.removeElementAt(idx);
367: vals.removeElementAt(idx);
368: }
369:
370: return rv;
371: }
372:
373: }
|