001: /*******************************************************************************
002: * Copyright (c) 2003, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal.intro.impl.model.url;
011:
012: import java.io.ByteArrayOutputStream;
013: import java.io.UnsupportedEncodingException;
014: import java.net.MalformedURLException;
015: import java.net.URL;
016: import java.util.Properties;
017:
018: import org.eclipse.ui.internal.intro.impl.util.Log;
019: import org.eclipse.ui.internal.intro.impl.util.StringUtil;
020:
021: /**
022: * A parser that knows how to parser OOBE action URLs. If URL is a valid intro
023: * url, it will create an instance of the IntroURL class.
024: */
025: public class IntroURLParser {
026:
027: // private String url_string = null;
028: private boolean hasProtocol = false;
029: private boolean isIntroUrl = false;
030:
031: private URL url_inst;
032:
033: /**
034: * Constructor that gets the URL to parse.
035: */
036: public IntroURLParser(String url) {
037: // create a URL instance, and parser it for parameters.
038: parseUrl(url);
039: }
040:
041: private void parseUrl(String url) {
042: if (url == null)
043: return;
044: url_inst = null;
045: try {
046: url_inst = new URL(url);
047: } catch (MalformedURLException e) {
048: // not a valid URL. set state.
049: return;
050: }
051:
052: if (url_inst.getProtocol() != null) {
053: // URL has some valid protocol. Check to see if it is an intro url.
054: hasProtocol = true;
055: isIntroUrl = isIntroUrl(url_inst);
056: return;
057: }
058:
059: // not an Intro URL. do nothing.
060: return;
061: }
062:
063: /**
064: * @return Returns the hasProtocol.
065: */
066: public boolean hasProtocol() {
067: return hasProtocol;
068: }
069:
070: /**
071: * @return Returns the isIntroUrl.
072: */
073: public boolean hasIntroUrl() {
074: return isIntroUrl;
075: }
076:
077: /**
078: * @return Returns the currebt url Protocol.
079: */
080: public String getProtocol() {
081: return url_inst.getProtocol();
082: }
083:
084: /**
085: * @return Returns the currebt url Protocol.
086: */
087: public String getHost() {
088: return url_inst.getHost();
089: }
090:
091: /**
092: * Checks to see if tha passed URL is an Intro URL. An intro URL is an http
093: * URL that has the intro plugin id as a host. eg:
094: * "http://org.eclipse.ui.intro/test".
095: *
096: * @param url
097: * @return true if url is an intro URL.
098: */
099: private boolean isIntroUrl(URL url) {
100: if (!url.getProtocol()
101: .equalsIgnoreCase(IntroURL.INTRO_PROTOCOL))
102: // quick exit. If it is not http, url is not an Intro url.
103: return false;
104:
105: if (url.getHost().equalsIgnoreCase(IntroURL.INTRO_HOST_ID))
106: return true;
107:
108: return false;
109: }
110:
111: /**
112: * @return Returns the introURL. Will be null if the parsed URL is not an
113: * Intro URL.
114: */
115: public IntroURL getIntroURL() {
116: IntroURL introURL = null;
117: if (isIntroUrl) {
118: // valid intro URL. Extract the action and parameters.
119: String action = getPathAsAction(url_inst);
120: Properties parameters = getQueryParameters(url_inst);
121:
122: // class instance vars are already populated by now.
123: introURL = new IntroURL(action, parameters);
124: }
125: return introURL;
126: }
127:
128: /**
129: * Retruns the path attribute of the passed URL, stripped out of the leading
130: * "/". Returns null if the url does not have a path.
131: *
132: * @param url
133: * @return
134: */
135: private String getPathAsAction(URL url) {
136: // get possible action.
137: String action = url.getPath();
138: // remove leading "/" from path.
139: if (action != null)
140: action = action.substring(1);
141: return action;
142: }
143:
144: /**
145: * Retruns the Query part of the URL as an instance of a Properties class.
146: *
147: * @param url
148: * @return
149: */
150: public Properties getQueryParameters(URL url) {
151: // parser all query parameters.
152: Properties properties = new Properties();
153: String query = url.getQuery();
154: if (query == null)
155: // we do not have any parameters in this URL, return an empty
156: // Properties instance.
157: return properties;
158:
159: // now extract the key/value pairs from the query.
160: String[] params = StringUtil.split(query, "&"); //$NON-NLS-1$
161: for (int i = 0; i < params.length; i++) {
162: // for every parameter, ie: key=value pair, create a property
163: // entry. we know we have the key as the first string in the array,
164: // and the value as the second array.
165: String[] keyValuePair = StringUtil.split(params[i], "="); //$NON-NLS-1$
166: if (keyValuePair.length != 2) {
167: Log
168: .warning("Ignoring the following Intro URL parameter: " //$NON-NLS-1$
169: + params[i]);
170: continue;
171: }
172:
173: String key = urlDecode(keyValuePair[0]);
174: if (key == null) {
175: Log
176: .warning("Failed to URL decode key: " + keyValuePair[0]); //$NON-NLS-1$
177: continue;
178: }
179:
180: String value = urlDecode(keyValuePair[1]);
181: if (value == null) {
182: Log
183: .warning("Failed to URL decode value: " + keyValuePair[1]); //$NON-NLS-1$
184: continue;
185: }
186:
187: properties.setProperty(key, value);
188: }
189: return properties;
190: }
191:
192: /*
193: * Note: This was copied and adapted from org.eclipse.help.internal.util.URLCoder
194: */
195: private static String urlDecode(String encodedURL) {
196: int len = encodedURL.length();
197: ByteArrayOutputStream os = new ByteArrayOutputStream(len);
198:
199: try {
200: for (int i = 0; i < len;) {
201: switch (encodedURL.charAt(i)) {
202: case '%':
203: if (len >= i + 3) {
204: os.write(Integer.parseInt(encodedURL.substring(
205: i + 1, i + 3), 16));
206: }
207: i += 3;
208: break;
209: case '+': // exception from standard
210: os.write(' ');
211: i++;
212: break;
213: default:
214: os.write(encodedURL.charAt(i++));
215: break;
216: }
217: }
218: return new String(os.toByteArray(), "UTF8"); //$NON-NLS-1$
219: } catch (UnsupportedEncodingException ex) {
220: return null;
221: }
222: }
223:
224: }
|