001: /*
002: * Copyright 2001 Sun Microsystems, Inc. All rights reserved.
003: * PROPRIETARY/CONFIDENTIAL. Use of this product is subject to license terms.
004: */
005:
006: package com.sun.portal.search.admin.model;
007:
008: import java.lang.*;
009: import java.util.*;
010: import java.util.logging.Logger;
011: import java.util.logging.Level;
012: import java.io.*;
013: import java.text.*;
014:
015: import javax.servlet.http.HttpServletRequest;
016:
017: import com.iplanet.jato.view.*;
018: import com.iplanet.jato.model.*;
019: import com.iplanet.jato.util.*;
020:
021: import com.sun.portal.search.rdmserver.*;
022: import com.sun.portal.search.rdmgr.*;
023: import com.sun.portal.search.util.SearchConfig;
024: import com.sun.portal.search.util.PBlock;
025: import com.sun.portal.search.admin.CSConfig;
026:
027: import com.sun.portal.search.admin.model.*;
028: import com.sun.portal.search.admin.resources.SearchResource;
029: import com.sun.portal.log.common.PortalLogger;
030:
031: public class PopularSearchModel extends DefaultModel {
032:
033: // Create a Logger for this class
034: private static Logger debugLogger = PortalLogger
035: .getLogger(PopularSearchModel.class);
036:
037: class SearchFreq {
038: String scope;
039: int freq;
040: boolean isBrowse;
041:
042: SearchFreq(String scopeStr, int initFreq, boolean browse) {
043: scope = scopeStr;
044: freq = initFreq;
045: isBrowse = browse;
046: }
047:
048: void inc() {
049: freq++;
050: }
051: }
052:
053: String serverRoot = null;
054: Date firstDate = null;
055: Date lastUpdated = null;
056: HashMap logs = new HashMap();
057: ArrayList sortedSearch = new ArrayList();
058: int numberOfQuery = 0;
059: public Locale userLocale = Locale.getDefault();
060: static final String DELIMITER = " --> ";
061:
062: static public void main(String[] args) {
063: CSConfig.init(args[0]);
064: PopularSearchModel ps = new PopularSearchModel();
065: SearchConfig csidConf = SearchConfig.getSearchConfig();
066: if (csidConf == null) {
067: try {
068: SearchConfig.init(ps.serverRoot + File.separator
069: + SearchConfig.CONFDIR + File.separator
070: + SearchConfig.SEARCH_CONF);
071: csidConf = SearchConfig.getSearchConfig();
072: } catch (Exception e) {
073: System.out.println("Error on SearchConfig.init():"
074: + e.getMessage());
075: return;
076: }
077: }
078: ps.execute(true);
079: System.out.println(ps.getReport());
080: }
081:
082: public PopularSearchModel() {
083: serverRoot = CSConfig.getServerRoot();
084: try {
085: readFromCache();
086: } catch (Exception e) {
087: debugLogger.finer("PSSH_CSPSAM0031");
088: execute(false);
089: }
090: }
091:
092: public PopularSearchModel(String name) {
093: serverRoot = CSConfig.getServerRoot();
094: }
095:
096: public void execute(boolean skipBrowse) {
097: String fileName = SearchConfig.getValue(SearchConfig.RDM_LOGFN);
098: BufferedReader in = null;
099: String line = null;
100: try {
101: in = new BufferedReader(new InputStreamReader(
102: new FileInputStream(fileName), "UTF-8"));
103: while ((line = in.readLine()) != null) {
104: Map pb = new HashMap();
105: try {
106: PBlock.str2pblock(line, pb);
107: } catch (Exception e) {
108: continue;
109: }
110:
111: String scopeStr = (String) pb.get("scope");
112: if (scopeStr == null) {
113: continue;
114: }
115: String RDMValue = (String) pb.get("RDM");
116: String qlValue = (String) pb.get("ql");
117: boolean searchOnTax = (RDMValue != null && RDMValue
118: .equalsIgnoreCase("tax"));
119: boolean searchOnRD = (RDMValue != null && RDMValue
120: .equalsIgnoreCase("RD"));
121: boolean isBrowsing = (qlValue != null && qlValue
122: .equalsIgnoreCase("taxonomy-basic"));
123: boolean isSearch = (qlValue != null && qlValue
124: .equalsIgnoreCase("search"));
125: if (skipBrowse && isBrowsing) {
126: continue;
127: }
128:
129: int rdmTaxIndex = line.indexOf("RDM=tax");
130: int rdmRDIndex = -1;
131: int qlCompassIndex = line.indexOf("ql=search");
132: int qlTaxBasicIndex = line.indexOf("ql=taxonomy-basic");
133: if (rdmTaxIndex < 0) {
134: rdmRDIndex = line.indexOf("RDM=rd");
135: }
136: if (rdmTaxIndex > 0) {
137: if (qlCompassIndex > 0 || skipBrowse
138: && qlTaxBasicIndex > 0) {
139: continue;
140: }
141: }
142: if (firstDate == null) {
143: int ds = line.indexOf('[');
144: int de = line.indexOf(']');
145: if (ds >= 0 && de > 0) {
146: DateFormat df = new SimpleDateFormat(
147: "dd/MMM/yyyy:HH:mm:ss");
148: String dstr = line.substring(ds + 1, de);
149: try {
150: firstDate = df.parse(dstr);
151: } catch (Exception e) {
152: }
153: }
154: }
155: //String scopeStr = line.substring(scopeIndex+7);
156: //int ndx = scopeStr.indexOf('"'); //xxx might need to deal with '"' in scope
157: //if (ndx >0 ) {
158: // scopeStr = scopeStr.substring(0, ndx);
159: //}
160: String browse = null;
161: String search = null;
162: String upScopeStr = scopeStr.toUpperCase();
163:
164: if (rdmRDIndex > 0 && qlCompassIndex > 0) {
165: if (upScopeStr.startsWith("(CLASSIFICATION")
166: || upScopeStr
167: .startsWith("<NOT> (CLASSIFICATION")) {
168: continue;
169: }
170: }
171:
172: if (isBrowsing && scopeStr.startsWith("children* ")) {
173: String classNodeName = scopeStr.substring(10);
174: if (classNodeName.equals("ROOT")) {
175: continue; //skip browse ROOT
176: }
177: browse = SearchResource.geti18nString(
178: "popsearch.browse", userLocale)
179: + " " + classNodeName;
180: } else if (qlCompassIndex > 0
181: && scopeStr
182: .startsWith("(Classification <STARTS> ")) {
183: int firstRB = scopeStr.indexOf(')');
184: if (firstRB > 0) {
185: int andIndex = scopeStr.indexOf("<AND>",
186: firstRB);
187: if (andIndex > 0) {
188: int secondLB = scopeStr.indexOf('(',
189: andIndex);
190: int secondRB = scopeStr.lastIndexOf(')');
191: if (secondRB > secondLB) {
192: search = scopeStr.substring(
193: secondLB + 1, secondRB)
194: + SearchResource.geti18nString(
195: "within", userLocale)
196: + scopeStr.substring(25,
197: firstRB);
198: }
199: }
200: }
201: } else if (qlCompassIndex > 0) {
202: search = scopeStr;
203: }
204: String key = null;
205: if (browse != null) {
206: key = browse;
207: } else if (search != null) {
208: key = search;
209: }
210: if (key != null) {
211: SearchFreq value = (SearchFreq) logs.get(key);
212: if (value == null) {
213: value = new SearchFreq(key, 1, browse != null);
214: logs.put(key, value);
215: } else {
216: value.inc();
217: }
218: }
219:
220: }
221:
222: } catch (IOException e) {
223: debugLogger.log(Level.INFO, "PSSH_CSPSAM0012", e
224: .getMessage());
225: }
226: sortedSearch.clear();
227: numberOfQuery = 0;
228: Iterator it = logs.keySet().iterator();
229: while (it.hasNext()) {
230: int i;
231: String key = (String) it.next();
232: SearchFreq sf = (SearchFreq) logs.get(key);
233: numberOfQuery += sf.freq;
234: for (i = 0; i < sortedSearch.size(); i++) {
235: SearchFreq curr = (SearchFreq) sortedSearch.get(i);
236: if (sf.freq > curr.freq) {
237: break;
238: }
239: }
240: sortedSearch.add(i, sf);
241: }
242: lastUpdated = new Date();
243: try {
244: writeToCache();
245: } catch (Exception e) {
246: //ignore
247: }
248:
249: return;
250: }
251:
252: private void readFromCache() throws Exception {
253: String fileName = serverRoot + File.separator + "logs"
254: + File.separator + "popularsearch.cache";
255: File file = new File(fileName);
256: long lastmodified = file.lastModified();
257: lastUpdated = new Date(lastmodified);
258: BufferedReader in = new BufferedReader(new InputStreamReader(
259: new FileInputStream(fileName), "UTF-8"));
260: String line;
261: boolean gotSince = false;
262: sortedSearch.clear();
263: while ((line = in.readLine()) != null) {
264: String name = null;
265: String value = null;
266: int ndx = line.indexOf(DELIMITER);
267: if (ndx < 0) {
268: continue;
269: }
270: name = line.substring(0, ndx);
271: value = line.substring(ndx + DELIMITER.length());
272: debugLogger.log(Level.FINER, "PSSH_CSPSAM0032",
273: new String[] { name, value });
274: if (!gotSince && name.equals("firstDate")) {
275: firstDate = DateFormat.getDateInstance().parse(value);
276: gotSince = true;
277: } else {
278: SearchFreq sf = new SearchFreq(name, Integer
279: .parseInt(value), false);
280: numberOfQuery += Integer.parseInt(value);
281: sortedSearch.add(sf);
282: }
283: }
284: }
285:
286: private void writeToCache() throws Exception {
287: String fileName = serverRoot + File.separator + "logs"
288: + File.separator + "popularsearch.cache";
289: FileOutputStream fout = new FileOutputStream(fileName);
290: PrintWriter out = new PrintWriter(new BufferedWriter(
291: new OutputStreamWriter(fout, "UTF-8")), true);
292: out.println("firstDate" + DELIMITER
293: + DateFormat.getDateInstance().format(firstDate));
294: for (int i = 0; i < getSize(); i++) {
295: out.println(getScope(i) + DELIMITER + getFreq(i));
296: }
297: out.close();
298: }
299:
300: public String getReport() {
301: StringBuffer sb = new StringBuffer();
302: sb.append("<p><pre>\n");
303: sb.append("Most popular user searches. \n");
304: if (numberOfQuery == 1) {
305: sb.append("1 query");
306: } else if (numberOfQuery > 1) {
307: sb.append(Integer.toString(numberOfQuery) + " queries");
308: } else {
309: sb.append("No queries");
310: }
311: DateFormat df = new SimpleDateFormat("EEE, MMM d, yyyy");
312: if (firstDate != null) {
313: String dateString = df.format(firstDate);
314: sb.append(" examined since " + dateString);
315: }
316: sb.append("\n\n");
317:
318: for (int i = 0; i < sortedSearch.size(); i++) {
319: SearchFreq sf = (SearchFreq) sortedSearch.get(i);
320: sb.append(Integer.toString(sf.freq) + "- " + sf.scope
321: + "\n");
322: }
323: sb.append("</pre>");
324: return sb.toString();
325: }
326:
327: public int getSize() {
328: return sortedSearch.size();
329: }
330:
331: public int getFreq(int index) {
332: try {
333: SearchFreq sf = (SearchFreq) sortedSearch.get(index);
334: if (sf != null)
335: return sf.freq;
336: } catch (Exception e) {
337: }
338: return 0;
339: }
340:
341: public String getScope(int index) {
342: try {
343: SearchFreq sf = (SearchFreq) sortedSearch.get(index);
344: if (sf != null)
345: return sf.scope;
346: } catch (Exception e) {
347: }
348: return null;
349: }
350:
351: public Date getFirstDate() {
352: return firstDate;
353: }
354:
355: public int getNumberOfQuery() {
356: return numberOfQuery;
357: }
358:
359: public Date getLastUpdated() {
360: return lastUpdated;
361: }
362:
363: }
|