001: /******************************************************************************
002: * JBoss, a division of Red Hat *
003: * Copyright 2006, Red Hat Middleware, LLC, and individual *
004: * contributors as indicated by the @authors tag. See the *
005: * copyright.txt in the distribution for a full listing of *
006: * individual contributors. *
007: * *
008: * This is free software; you can redistribute it and/or modify it *
009: * under the terms of the GNU Lesser General Public License as *
010: * published by the Free Software Foundation; either version 2.1 of *
011: * the License, or (at your option) any later version. *
012: * *
013: * This software is distributed in the hope that it will be useful, *
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of *
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
016: * Lesser General Public License for more details. *
017: * *
018: * You should have received a copy of the GNU Lesser General Public *
019: * License along with this software; if not, write to the Free *
020: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
021: * 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
022: ******************************************************************************/package org.jboss.portal.widget.netvibes.provider;
023:
024: import java.net.MalformedURLException;
025: import java.net.URL;
026: import java.util.ArrayList;
027: import java.util.Arrays;
028: import java.util.List;
029:
030: import org.jboss.portal.common.i18n.LocalizedString;
031: import org.jboss.portal.common.net.URLTools;
032: import org.jboss.portal.common.text.FastURLEncoder;
033: import org.jboss.portal.widget.exceptions.WidgetException;
034: import org.jboss.portal.widget.exceptions.WidgetFetchException;
035: import org.jboss.portal.widget.exceptions.WidgetMetaDataParseException;
036: import org.jboss.portal.widget.exceptions.WidgetNotSupportedException;
037: import org.jboss.portal.widget.netvibes.NetvibesMetaData;
038: import org.jboss.portal.widget.netvibes.NetvibesPreferenceInfo;
039: import org.jboss.portal.widget.netvibes.NetvibesPreferencesInfo;
040: import org.jboss.portal.widget.netvibes.NetvibesWidgetInfo;
041: import org.jboss.portal.widget.netvibes.json.JSONArray;
042: import org.jboss.portal.widget.netvibes.json.JSONException;
043: import org.jboss.portal.widget.netvibes.json.JSONObject;
044: import org.jboss.portal.widget.netvibes.json.JSONObjectWrapper;
045: import org.jboss.portal.widget.netvibes.type.NVBooleanType;
046: import org.jboss.portal.widget.netvibes.type.NVDataType;
047: import org.jboss.portal.widget.netvibes.type.NVHiddenType;
048: import org.jboss.portal.widget.netvibes.type.NVListType;
049: import org.jboss.portal.widget.netvibes.type.NVPasswordType;
050: import org.jboss.portal.widget.netvibes.type.NVRangeType;
051: import org.jboss.portal.widget.netvibes.type.NVTextType;
052: import org.jboss.portal.widget.netvibes.type.NVTextareaType;
053:
054: /**
055: * @author <a href="mailto:emuckenh@redhat.com">Emanuel Muckenhuber</a>
056: * @version $Revision$
057: */
058: public class NetvibesJSONInfoBuilder {
059:
060: /** The URL */
061: private final URL url;
062:
063: /** . */
064: private static final String COULD_NOT_PARSE = "/* String could not be parsed as XML */ null";
065:
066: public NetvibesJSONInfoBuilder(URL url) {
067: if (url == null) {
068: throw new IllegalArgumentException("Url must not be null.");
069: }
070:
071: this .url = url;
072: }
073:
074: private URL buildNetvibesJSONUrl(URL url)
075: throws MalformedURLException {
076: StringBuffer jsonUrl = new StringBuffer();
077: jsonUrl
078: .append("http://www.netvibes.com/api/uwa/compile/uwa_json.php?moduleUrl=");
079: jsonUrl.append(FastURLEncoder.getUTF8Instance().encode(
080: url.toString()));
081:
082: return new URL(jsonUrl.toString());
083: }
084:
085: public NetvibesWidgetInfo create() throws WidgetException {
086: try {
087: byte[] bytes = obtainWidget(this .url);
088: if (bytes == null) {
089: throw new WidgetFetchException(
090: "Could not retreive widget: " + url.toString());
091: }
092:
093: // If requested widget is not uwa conform it returns : String could not be parsed as XML
094: if (Arrays.equals(bytes, COULD_NOT_PARSE.getBytes())) {
095: throw new WidgetMetaDataParseException(
096: "Could not parse widget meta data: "
097: + url.toString());
098: }
099:
100: // Create JSONObject
101: JSONObject jsonResponse = new JSONObject(new String(bytes));
102:
103: // Getting the title
104: LocalizedString title = new LocalizedString(jsonResponse
105: .getString("title"));
106:
107: if (title == null) {
108: throw new WidgetMetaDataParseException(
109: "Unsupported widget format: " + url.toString());
110: }
111:
112: // Getting the icons
113: List iconList = null;
114: try {
115: iconList = this .parseIcons(jsonResponse
116: .getJSONObject("icon"));
117: } catch (JSONException e) {
118: iconList = new ArrayList();
119: }
120:
121: // Parsing the metadata
122: JSONObject metadata = new JSONObjectWrapper(jsonResponse
123: .getJSONObject("metas"));
124:
125: LocalizedString description = null;
126: if (metadata.getString("description") != null) {
127: description = new LocalizedString(metadata
128: .getString("description"));
129: }
130:
131: NetvibesMetaData md = new NetvibesMetaData(metadata
132: .getString("author"),
133: metadata.getString("website"), description,
134: metadata.getString("version"), metadata
135: .getString("keywords"), metadata
136: .getString("screenshot"), metadata
137: .getString("thumbnail"), metadata
138: .getString("apiVersion"), metadata
139: .getBoolean("debugMode"), metadata
140: .getInt("autoRefresh"), metadata
141: .getBoolean("inline"));
142:
143: // Checking UWA compatible version
144: int version = metadata.getInt("apiVersion");
145: if (version < 1) {
146: throw new WidgetNotSupportedException(
147: "Not supported widget version.");
148: }
149:
150: // Netvibes preferences
151: List<NetvibesPreferenceInfo> preferences = new ArrayList<NetvibesPreferenceInfo>();
152: JSONArray array = jsonResponse.getJSONArray("preferences");
153: for (int i = 0; i < array.length(); i++) {
154: JSONObject preference = new JSONObjectWrapper(array
155: .getJSONObject(i));
156:
157: NVDataType type = null;
158:
159: int dataType = NVDataType
160: .parseDataTypeLiteral(preference
161: .getString("type"));
162: switch (dataType) {
163: case NVDataType.TEXT:
164: type = NVTextType.getInstance();
165: break;
166: case NVDataType.BOOLEAN:
167: type = NVBooleanType.getInstance();
168: break;
169: case NVDataType.HIDDEN:
170: type = NVHiddenType.getInstance();
171: break;
172: case NVDataType.PASSWORD:
173: type = NVPasswordType.getInstance();
174: break;
175: case NVDataType.TEXTAREA:
176: type = NVTextareaType.getInstance();
177: break;
178: case NVDataType.RANGE:
179: type = new NVRangeType(preference.getInt("min"),
180: preference.getInt("max"), preference
181: .getInt("step"));
182: break;
183: case NVDataType.LIST:
184: List<NVListType.NVListValue> valueList = new ArrayList();
185: JSONArray values = preference
186: .getJSONArray("options");
187: for (int j = 0; j < values.length(); j++) {
188: JSONObject value = values.getJSONObject(j);
189: String key = value.getString("value");
190: LocalizedString label = new LocalizedString(
191: value.getString("label"));
192: NVListType.NVListValue nvValue = new NVListType.NVListValue(
193: key, label);
194: valueList.add(nvValue);
195: }
196: type = new NVListType(valueList);
197: break;
198: }
199:
200: NetvibesPreferenceInfo info = new NetvibesPreferenceInfo(
201: preference.getString("name"), preference
202: .getString("label"), type, preference
203: .getString("onchange"), preference
204: .getString("defaultValue"));
205:
206: preferences.add(info);
207: }
208:
209: NetvibesPreferencesInfo preferencesInfo = new NetvibesPreferencesInfo(
210: preferences);
211:
212: NetvibesWidgetInfo info = new NetvibesWidgetInfo(title,
213: iconList, md, preferencesInfo);
214:
215: return info;
216: } catch (JSONException e) {
217: throw new WidgetMetaDataParseException(
218: "Could not parse widget meta data: "
219: + url.toString(), e);
220: } catch (MalformedURLException e) {
221: throw new WidgetFetchException("Unable to build url.", e);
222: }
223:
224: }
225:
226: private List parseIcons(JSONObject icons) throws JSONException {
227: List iconList = new ArrayList();
228: for (int i = 0; i < icons.length(); i++) {
229: iconList.add(icons.getString(String.valueOf(i)));
230: }
231: return iconList;
232: }
233:
234: public URL getUrl() {
235: return url;
236: }
237:
238: /**
239: * needed for testing
240: * @throws MalformedURLException
241: * @throws IllegalArgumentException
242: */
243: protected byte[] obtainWidget(URL url)
244: throws IllegalArgumentException, MalformedURLException {
245: return obtainURL(url);
246: }
247:
248: /**
249: * creating correct url here to be able to also get local sources for testing
250: * @throws MalformedURLException
251: * @throws IllegalArgumentException
252: */
253: private byte[] obtainURL(URL url) throws IllegalArgumentException,
254: MalformedURLException {
255: return URLTools.getContent(this .buildNetvibesJSONUrl(url),
256: 5000, 5000);
257: }
258: }
|