001: /*
002: License $Id: URI.java,v 1.7 2004/04/16 01:30:03 hendriks73 Exp $
003:
004: Copyright (c) 2001-2005 tagtraum industries.
005:
006: LGPL
007: ====
008:
009: jo! is free software; you can redistribute it and/or
010: modify it under the terms of the GNU Lesser General Public
011: License as published by the Free Software Foundation; either
012: version 2.1 of the License, or (at your option) any later version.
013:
014: jo! is distributed in the hope that it will be useful,
015: but WITHOUT ANY WARRANTY; without even the implied warranty of
016: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: Lesser General Public License for more details.
018:
019: You should have received a copy of the GNU Lesser General Public
020: License along with this library; if not, write to the Free Software
021: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022:
023: For LGPL see <http://www.fsf.org/copyleft/lesser.txt>
024:
025:
026: Sun license
027: ===========
028:
029: This release contains software by Sun Microsystems. Therefore
030: the following conditions have to be met, too. They apply to the
031: files
032:
033: - lib/mail.jar
034: - lib/activation.jar
035: - lib/jsse.jar
036: - lib/jcert.jar
037: - lib/jaxp.jar
038: - lib/crimson.jar
039: - lib/servlet.jar
040: - lib/jnet.jar
041: - lib/jaas.jar
042: - lib/jaasmod.jar
043:
044: contained in this release.
045:
046: a. Licensee may not modify the Java Platform
047: Interface (JPI, identified as classes contained within the javax
048: package or any subpackages of the javax package), by creating additional
049: classes within the JPI or otherwise causing the addition to or modification
050: of the classes in the JPI. In the event that Licensee creates any
051: Java-related API and distribute such API to others for applet or
052: application development, you must promptly publish broadly, an accurate
053: specification for such API for free use by all developers of Java-based
054: software.
055:
056: b. Software is confidential copyrighted information of Sun and
057: title to all copies is retained by Sun and/or its licensors. Licensee
058: shall not modify, decompile, disassemble, decrypt, extract, or otherwise
059: reverse engineer Software. Software may not be leased, assigned, or
060: sublicensed, in whole or in part. Software is not designed or intended
061: for use in on-line control of aircraft, air traffic, aircraft navigation
062: or aircraft communications; or in the design, construction, operation or
063: maintenance of any nuclear facility. Licensee warrants that it will not
064: use or redistribute the Software for such purposes.
065:
066: c. Software is provided "AS IS," without a warranty
067: of any kind. ALL EXPRESS OR IMPLIED REPRESENTATIONS AND WARRANTIES,
068: INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
069: PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
070:
071: d. This License is effective until terminated. Licensee may
072: terminate this License at any time by destroying all copies of Software.
073: This License will terminate immediately without notice from Sun if Licensee
074: fails to comply with any provision of this License. Upon such termination,
075: Licensee must destroy all copies of Software.
076:
077: e. Software, including technical data, is subject to U.S.
078: export control laws, including the U.S. Export Administration Act and its
079: associated regulations, and may be subject to export or import regulations
080: in other countries. Licensee agrees to comply strictly with all such
081: regulations and acknowledges that it has the responsibility to obtain
082: licenses to export, re-export, or import Software. Software may not be
083: downloaded, or otherwise exported or re-exported (i) into, or to a national
084: or resident of, Cuba, Iraq, Iran, North Korea, Libya, Sudan, Syria or any
085: country to which the U.S. has embargoed goods; or (ii) to anyone on the
086: U.S. Treasury Department's list of Specially Designated Nations or the U.S.
087: Commerce Department's Table of Denial Orders.
088:
089:
090: Feedback
091: ========
092:
093: We encourage your feedback and suggestions and want to use your feedback to
094: improve the Software. Send all such feedback to:
095: <feedback@tagtraum.com>
096:
097: For more information on tagtraum industries and jo!
098: please see <http://www.tagtraum.com/>.
099:
100:
101: */
102: package com.tagtraum.framework.http;
103:
104: import com.tagtraum.framework.util.UnSyncStringBuffer;
105: import com.tagtraum.framework.util.OrderedMap;
106: import com.tagtraum.perf.util.SingleDelimiterStringTokenizer;
107:
108: import java.io.Serializable;
109: import java.net.URLEncoder;
110: import java.util.*;
111:
112: /**
113: * Encapsulates a URI.
114: *
115: * @version 1.1beta1 $Id: URI.java,v 1.7 2004/04/16 01:30:03 hendriks73 Exp $
116: * @author Hendrik Schreiber
117: */
118: public class URI implements Serializable {
119:
120: /**
121: * Source-Version
122: */
123: public static String vcid = "$Id: URI.java,v 1.7 2004/04/16 01:30:03 hendriks73 Exp $";
124:
125: private SingleDelimiterStringTokenizer tokenizer;
126: /** The path. */
127: private String path;
128: /** Flag that indicate whether this URI has been parsed */
129: private boolean parsed;
130: /** QueryString. */
131: private String query;
132: /** String following ';' but preceding '?' */
133: private String parameter;
134: /** The URI. */
135: private String uri;
136: /** Flag, indicating a modification */
137: private boolean modified;
138: /** Hashtable containing the parameters */
139: private OrderedMap parameters;
140:
141: public URI() {
142: this .parameters = new OrderedMap();
143: this .tokenizer = new SingleDelimiterStringTokenizer();
144: }
145:
146: public URI(String uri) {
147: this ();
148: init(uri);
149: }
150:
151: /**
152: * Initializes this Object.
153: *
154: * @param uri der URI
155: */
156: public synchronized void init(String uri) {
157: this .uri = uri;
158: this .parsed = false;
159: }
160:
161: /**
162: * Parses the URI.
163: */
164: private void parse() {
165: if (parsed)
166: return;
167: parsed = true;
168: modified = false;
169: path = uri;
170: query = null;
171:
172: if (uri == null)
173: return;
174: int length = uri.length();
175: int q = uri.indexOf('?');
176: if (q >= 0) {
177: if ((q + 1) < length)
178: query = uri.substring(q + 1);
179: parseQueryString(query);
180: path = uri.substring(0, q);
181: } else {
182: parameters.clear();
183: }
184: int p = uri.indexOf(';');
185: if (p > 0 && p < q && p + 1 < length) {
186: parameter = uri.substring(p + 1, q);
187: path = uri.substring(0, p);
188: } else if (p > 0 && q < 0 && p + 1 < length) {
189: parameter = uri.substring(p + 1);
190: path = uri.substring(0, p);
191: } else {
192: parameter = null;
193: }
194: }
195:
196: /**
197: * Returns the path.
198: *
199: * @return the URI path
200: */
201: public String getPath() {
202: parse();
203: return path;
204: }
205:
206: /**
207: * Sets the path.
208: *
209: * @param aPath the URI path
210: */
211: public void setPath(String aPath) {
212: parse();
213: modified = true;
214: this .path = aPath;
215: }
216:
217: /**
218: * Sets the parameter (;parameter=...)
219: *
220: * @param aParameter
221: */
222: public void setParameter(String aParameter) {
223: parse();
224: this .modified = true;
225: this .parameter = aParameter;
226: }
227:
228: /**
229: * Returns the parameter (;parameter=...)
230: *
231: * @return the parameter
232: */
233: public String getParameter() {
234: parse();
235: return parameter;
236: }
237:
238: /**
239: * Return the URL encoded QueryString without leading questionmark
240: * or null, if there is no QueryString
241: *
242: * @return the QueryString or null
243: */
244: public synchronized String getQuery() {
245: parse();
246: if (modified && parameters != null) {
247: StringBuffer sb = new StringBuffer(256);
248: String key;
249: String[] value;
250: Iterator i = parameters.entryList().iterator();
251: while (i.hasNext()) {
252: Map.Entry entry = (Map.Entry) i.next();
253: key = (String) entry.getKey();
254: value = (String[]) entry.getValue();
255: for (int j = 0, max = value.length; j < max; j++) {
256: sb.append(URLEncoder.encode(key)); // correct?
257: sb.append('=');
258: sb.append(URLEncoder.encode(value[j]));
259: sb.append('&');
260: }
261: }
262: if (sb.length() > 0) {
263: sb.setLength(sb.length() - 1);
264: }
265: query = sb.length() > 0 ? sb.toString() : null;
266: }
267: return query;
268: }
269:
270: /**
271: * Returns an enumeration of the parameter names.
272: *
273: * @return enumeration of the parameter names.
274: */
275: public Enumeration getParameterNames() {
276: parse();
277: return new Enumeration() {
278: private Iterator entries = parameters.entryList()
279: .iterator();
280:
281: public boolean hasMoreElements() {
282: return entries.hasNext();
283: }
284:
285: public Object nextElement() {
286: if (!entries.hasNext())
287: throw new NoSuchElementException();
288: return ((Map.Entry) entries.next()).getKey();
289: }
290: };
291: }
292:
293: /**
294: * Returns a set of the parameter names.
295: *
296: * @return immutable set of parameter names
297: */
298: public Set getParameterNamesSet() {
299: // the key set of parameters is already unmodifiable.
300: return parameters.keySet();
301: }
302:
303: /**
304: * Deletes all parameternames.
305: */
306: public void clearParameters() {
307: parse();
308: modified = true;
309: parameters.clear();
310: }
311:
312: /**
313: * Adds a parameter.
314: *
315: * @param aName parametername
316: * @param aValue value
317: */
318: public void put(String aName, String aValue) {
319: put(aName, new String[] { aValue });
320: }
321:
322: /**
323: * Adds a parameterlist.
324: *
325: * @param aName parametername
326: * @param aValues values
327: */
328: public void put(String aName, String[] aValues) {
329: parse();
330: this .modified = true;
331: if (aName != null && aValues != null) {
332: if (parameters.containsKey(aName)) {
333: String oldVals[] = (String[]) parameters.get(aName);
334: String[] valArray = new String[oldVals.length
335: + aValues.length];
336: System.arraycopy(oldVals, 0, valArray, 0,
337: oldVals.length);
338: System.arraycopy(aValues, 0, valArray, oldVals.length,
339: aValues.length);
340: parameters.put(aName, valArray);
341: } else {
342: parameters.put(aName, aValues);
343: }
344: }
345: }
346:
347: /**
348: * Returns the first parameter value.
349: *
350: * @param aName name of the parameter
351: */
352: public String get(String aName) {
353: parse();
354: String s[] = (String[]) parameters.get(aName);
355: if (s != null && s.length > 0) {
356: return s[0];
357: }
358: return null;
359: }
360:
361: /**
362: * Returns all parameters.
363: *
364: * @param aName the Name of the parameters
365: */
366: public synchronized String[] getValues(String aName) {
367: parse();
368: return (String[]) parameters.get(aName);
369: }
370:
371: /**
372: * Removes a parameter.
373: *
374: * @param aName the Name of the parameter
375: */
376: public synchronized void remove(String aName) {
377: parse();
378: modified = true;
379: parameters.remove(aName);
380: }
381:
382: public String toString() {
383: if ((!parsed) || (!modified))
384: return uri;
385: UnSyncStringBuffer result = new UnSyncStringBuffer();
386: result.append(path);
387: if (parameter != null) {
388: result.append(';');
389: result.append(parameter);
390: }
391: if (modified)
392: getQuery();
393: if (query != null && query.length() > 0) {
394: result.append('?');
395: result.append(query);
396: }
397: return result.toString();
398: }
399:
400: public Object clone() {
401: return new URI(toString());
402: }
403:
404: /**
405: * Utility method that parses the querystring.
406: *
407: * @param s QueryString to parse
408: */
409: private void parseQueryString(String s) {
410: parameters.clear();
411: if (s == null)
412: return;
413: String valArray[] = null;
414: tokenizer.init(s, '&');
415: while (tokenizer.hasMoreTokens()) {
416: String pair = (String) tokenizer.nextToken();
417: int pos = pair.indexOf('=');
418: if (pos == -1)
419: continue;
420: try {
421: String key = com.tagtraum.framework.util.URLDecoder
422: .decode(pair.substring(0, pos));
423: String val = com.tagtraum.framework.util.URLDecoder
424: .decode(pair.substring(pos + 1, pair.length()));
425: if (parameters.containsKey(key)) {
426: String oldVals[] = (String[]) parameters.get(key);
427: valArray = new String[oldVals.length + 1];
428: System.arraycopy(oldVals, 0, valArray, 0,
429: oldVals.length);
430: valArray[oldVals.length] = val;
431: } else {
432: valArray = new String[] { val };
433: }
434: parameters.put(key, valArray);
435: } catch (Exception e) {
436: if (e instanceof IllegalArgumentException) {
437: throw (IllegalArgumentException) e;
438: }
439: }
440: }
441: }
442: }
|