2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
41
package org.netbeans.server.uihandler;
43
import org.netbeans.server.uihandler.statistics.*;
44
import org.netbeans.server.uihandler.*;
45
import java.io.IOException;
46
import java.io.InputStream;
47
import java.net.MalformedURLException;
49
import java.util.ArrayList;
50
import java.util.Collections;
51
import java.util.HashMap;
52
import java.util.LinkedList;
53
import java.util.List;
55
import java.util.Queue;
56
import java.util.Random;
58
import java.util.logging.Level;
59
import java.util.logging.Logger;
60
import javax.xml.parsers.ParserConfigurationException;
61
import javax.xml.parsers.SAXParser;
62
import javax.xml.parsers.SAXParserFactory;
63
import org.openide.util.Exceptions;
64
import org.openide.util.RequestProcessor;
65
import org.xml.sax.Attributes;
66
import org.xml.sax.SAXException;
67
import org.xml.sax.helpers.DefaultHandler;
69
/** Class that provides access to tip of the day functionality provided
70
* by docs team. It is created with URL refering to the page with XML data
71
* and is refereshed very hour.
73
* @author Jaroslav Tulach
75
public final class TipOfTheDay implements Runnable {
76
private static final Logger LOG = Logger.getLogger(TipOfTheDay.class.getName());
77
private static RequestProcessor RP = new RequestProcessor("Refresh TipOfTheDay");
79
private Map<String,List<Tip>> tips;
80
private final URL url;
81
private RequestProcessor.Task refresh;
83
private TipOfTheDay(URL url) {
86
tips = Collections.emptyMap();
89
tips = Collections.emptyMap();
91
refresh = RP.create(this);
95
refresh.waitFinished(10000);
96
} catch (InterruptedException ex) {
97
LOG.log(Level.WARNING, ex.getMessage(), ex);
101
/** Parses content provided by some URL and create the TipOfTheDay database.
102
* @param url url to read the TipOfTheDay from
104
public static TipOfTheDay create(URL url) {
105
return new TipOfTheDay(url);
108
private static TipOfTheDay DEFAULT;
109
/** Gets default tip of the day.
111
public static TipOfTheDay getDefault() {
112
if (DEFAULT == null) {
113
String tips = Utils.getVariable("tipsOfTheDay", String.class);
116
DEFAULT = new TipOfTheDay(new URL(tips));
117
} catch (MalformedURLException ex) {
118
LOG.log(Level.WARNING, ex.getMessage(), ex);
121
if (DEFAULT == null) {
122
return new TipOfTheDay(null);
128
/** Refreshes the content of the databases. Re-reads the content of
129
* the provided URL and updates internal structures.
132
LOG.info("Refreshing content of TipOfTheDay: " + url); // NOI18N
134
Parser p = new Parser();
137
} catch (SAXException ex) {
138
LOG.log(Level.WARNING, ex.getMessage(), ex);
139
} catch (ParserConfigurationException ex) {
140
LOG.log(Level.WARNING, ex.getMessage(), ex);
141
} catch (IOException ex) {
142
LOG.log(Level.WARNING, ex.getMessage(), ex);
144
LOG.info("Done refreshing of TipOfTheDay"); // NOI18N
145
refresh.schedule(60 * 1000 * 60);
149
/** Finds appropriate tip of the date for given usage of projects.
150
* @param cnts collected info from ProjectTypes
151
* @return randomly selected typ
153
public Tip find(Set<Map.Entry<String,Integer>> cnts) {
154
List<? extends Tip> all = findAll(cnts);
158
int r = new Random().nextInt(all.size());
162
/** Finds all tips appropriate as tip of the date for given usage of projects.
163
* @param cnts the counts
164
* @return list of possible tips
166
public List<? extends Tip> findAll(Set<Map.Entry<String,Integer>> cnts) {
168
List<Tip> found = Collections.emptyList();
173
for (Map.Entry<String, Integer> entry : cnts) {
174
if (entry.getValue() > max) {
175
List<Tip> f = tips.get(entry.getKey());
177
max = entry.getValue();
186
static String findProject(String category) throws SAXException {
188
if ("Web and Enterprise Development".equals(category)) { // NOI18N
189
ret = "Ear"; // NOI18N
191
if ("NetBeans Platform Development".equals(category)) { // NOI18N
192
ret = "NbModule"; // NOI18N
194
if ("Swing GUI Development".equals(category)) { // NOI18N
195
ret = "j2se"; // NOI18N
197
if ("Monitoring and Profiling".equals(category)) { // NOI18N
200
if ("Mobile Application Development".equals(category)) { // NOI18N
201
ret = "J2ME"; // NOI18N
203
if ("Advanced and Miscellaneous".equals(category)) { // NOI18N
204
ret = "J2SE"; // NOI18N
206
if ("Basic IDE Functionality".equals(category)) { // NOI18N
207
ret = "J2SE"; // NOI18N
211
throw new SAXException("Unexpected category: " + category);
217
/** Represents info about one tip.
219
public static final class Tip {
225
public String getDescription() {
229
public String getUrl() {
233
public String getTitle() {
241
<date>2007-03-05 00:00:00</date>
242
<title>NetBeans IDE 6.0 GUI Builder Demo</title>
243
<description>In this preview the NetBeans IDE 6.0, you will see how much easier it is to develop Java desktop applications with the improved GUI Builder. You'll see the tools which take advantage of both the Swing Application framework(JSR 296) and Beans Binding(JSR 295). Check it out!</description>
244
<category>Swing GUI Development</category>
245
<url>http://www.netbeans.org/download/flash/netbeans_6_gui_builder/netbeans_6_gui_builder.html</url>
248
private static final class Parser extends DefaultHandler {
249
private Map<String,List<Tip>> tips = new HashMap<String, List<TipOfTheDay.Tip>>();
251
private Queue<StringBuilder> values = new LinkedList<StringBuilder>();
253
public Map<String,List<Tip>> parse(URL url) throws SAXException, ParserConfigurationException, IOException {
254
SAXParserFactory f = SAXParserFactory.newInstance();
255
SAXParser p = f.newSAXParser();
256
InputStream is = url.openStream();
263
public void startElement(String uri, String local, String qName, Attributes args) throws SAXException {
264
if (LOG.isLoggable(Level.FINEST)) {
265
LOG.finest("startElement uri: " + uri + " local: " + local + " qName: " + qName); // NOI18N
267
if (qName.equals("article")) {
268
assert current == null;
272
values.add(new StringBuilder());
276
public void characters(char[] characters, int from, int len) throws SAXException {
277
assert !values.isEmpty();
279
StringBuilder value = values.peek();
280
if (LOG.isLoggable(Level.FINEST)) {
281
LOG.finest("characters: " + new String(characters, from, len)); // NOI18N
283
value.append(characters, from, len);
289
public void endElement(String uri, String local, String qName) throws SAXException {
290
assert !values.isEmpty();
292
StringBuilder value = values.poll();
293
for (int i = 0; i < value.length(); i++) {
294
if (!Character.isWhitespace(value.charAt(i))) {
299
for (int i = value.length() - 1; i > 0; i--) {
300
if (!Character.isWhitespace(value.charAt(i))) {
301
value.delete(i + 1, value.length());
306
if (LOG.isLoggable(Level.FINEST)) {
307
LOG.finest("endElement uri: " + uri + " local: " + local + " qName: " + qName); // NOI18N
309
if (qName.equals("article")) { // NOI18N
310
assert current != null;
311
String prj = findProject(current.category);
312
List<Tip> arr = tips.get(prj);
314
arr = new ArrayList<Tip>();
322
if (qName.equals("description")) { // NOI18N
323
assert current != null;
324
assert value != null;
325
current.description = value.toString();
328
if (qName.equals("title")) { // NOI18N
329
assert current != null;
330
assert value != null;
331
current.title = value.toString();
334
if (qName.equals("url")) { // NOI18N
335
assert current != null;
336
assert value != null;
337
current.url = value.toString();
340
if (qName.equals("category")) { // NOI18N
341
assert current != null;
342
assert value != null;
343
current.category = value.toString();