001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.portals.gems.browser;
018:
019: import java.io.IOException;
020: import java.util.ArrayList;
021: import java.util.Iterator;
022: import java.util.List;
023: import java.util.Vector;
024:
025: import javax.portlet.ActionRequest;
026: import javax.portlet.ActionResponse;
027: import javax.portlet.PortletContext;
028: import javax.portlet.PortletException;
029: import javax.portlet.PortletMode;
030: import javax.portlet.PortletConfig;
031: import javax.portlet.PortletPreferences;
032: import javax.portlet.PortletRequest;
033: import javax.portlet.PortletSession;
034: import javax.portlet.RenderRequest;
035: import javax.portlet.RenderResponse;
036:
037: import org.apache.commons.logging.Log;
038: import org.apache.commons.logging.LogFactory;
039: import org.apache.jetspeed.sso.SSOProvider;
040: import org.apache.portals.bridges.velocity.GenericVelocityPortlet;
041: import org.apache.portals.gems.util.StatusMessage;
042: import org.apache.portals.messaging.PortletMessaging;
043: import org.apache.velocity.context.Context;
044:
045: /**
046: * AbstractBrowserPortlet
047: *
048: * @author <a href="mailto:taylor@apache.org">David Sean Taylor </a>
049: * @version $Id: AbstractBrowserPortlet.java,v 1.2 2005/01/01 00:01:29 taylor
050: * Exp $
051: */
052: public class BrowserPortlet extends GenericVelocityPortlet implements
053: Browser {
054:
055: protected static final String SQL = "sql";
056:
057: protected static final String POOLNAME = "poolname";
058:
059: protected static final String START = "start";
060: protected static final String FIND = "find";
061: protected static final String SEARCH_STRING = "searchString";
062: protected static final String SEARCH_COLUMN = "searchColumn";
063: protected static final String FILTERED = "filtered";
064: protected static final String FILTER = "filter";
065:
066: protected static final String CUSTOMIZE_TEMPLATE = "customizeTemplate";
067:
068: protected static final String WINDOW_SIZE = "WindowSize";
069:
070: protected static final String USER_OBJECT_NAMES = "user-object-names";
071:
072: protected static final String USER_OBJECT_TYPES = "user-object-types";
073:
074: protected static final String USER_OBJECTS = "user-objects";
075:
076: protected static final String SQL_PARAM_PREFIX = "sqlparam";
077:
078: protected static final String LINKS_READ = "linksRead";
079:
080: protected static final String ROW_LINK = "rowLinks";
081:
082: protected static final String TABLE_LINK = "tableLinks";
083:
084: protected static final String ROW_LINK_IDS = "row-link-ids";
085:
086: protected static final String ROW_LINK_TYPES = "row-link-types";
087:
088: protected static final String ROW_LINK_TARGETS = "row-link-targets";
089:
090: protected static final String TABLE_LINK_IDS = "table-link-ids";
091:
092: protected static final String TABLE_LINK_TYPES = "table-link-types";
093:
094: protected static final String TABLE_LINK_TARGETS = "table-link-targets";
095:
096: protected static final String BROWSER_TABLE_SIZE = "tableSize";
097:
098: protected static final String BROWSER_ACTION_KEY = "browser_action_key";
099:
100: protected static final String BROWSER_ITERATOR = "table";
101:
102: protected static final String BROWSER_TITLE_ITERATOR = "title";
103:
104: protected static final String NEXT = "next";
105:
106: protected static final String PREVIOUS = "prev";
107:
108: protected static final String FIRST = "first";
109:
110: protected static final String LAST = "last";
111:
112: protected static final String VELOCITY_NULL_ENTRY = "-";
113:
114: // portlet entry Id
115: protected static final String PEID = "js_peid";
116:
117: protected static final String SORT_COLUMN_NAME = "js_dbcolumn";
118:
119: protected List sqlParameters = new Vector();
120:
121: /*
122: * SSO link
123: */
124: protected PortletContext context;
125: protected SSOProvider sso;
126:
127: /**
128: * Static initialization of the logger for this class
129: */
130: protected Log log = LogFactory.getLog(BrowserPortlet.class);
131:
132: public void init(PortletConfig config) throws PortletException {
133: super .init(config);
134:
135: context = getPortletContext();
136: sso = (SSOProvider) context.getAttribute("cps:SSO");
137: if (null == sso) {
138: log.info("Warning: SSO provider not found.");
139: //throw new PortletException("Failed to find SSO Provider on portlet initialization");
140: }
141: }
142:
143: public void getRows(RenderRequest request, String sql,
144: int windowSize) throws Exception {
145: }
146:
147: public void getRows(RenderRequest request, String sql,
148: int windowSize, String filter) throws Exception {
149: }
150:
151: public void doView(RenderRequest request, RenderResponse response)
152: throws PortletException, IOException {
153: int resultSetSize, next, prev, windowSize;
154:
155: response.setContentType("text/html");
156:
157: BrowserIterator iterator = getBrowserIterator(request);
158: Context context = this .getContext(request);
159:
160: String sortColName = request.getParameter(SORT_COLUMN_NAME);
161: int start = getStartVariable(request, START, sortColName,
162: iterator);
163:
164: PortletPreferences prefs = request.getPreferences();
165:
166: windowSize = Integer
167: .parseInt(prefs.getValue(WINDOW_SIZE, "10"));
168:
169: StatusMessage message = (StatusMessage) PortletMessaging
170: .consume(request, "DatabaseBrowserPortlet", "action");
171: if (message != null) {
172: this .getContext(request).put("statusMsg", message);
173: }
174:
175: try {
176: if (iterator == null) {
177: String sql = getQueryString(request, context);
178: // System.out.println("buildNormalContext SQL: "+sql);
179: readUserParameters(request, context);
180: String filter = request.getParameter(FILTER);
181: if (filter != null)
182: getRows(request, sql, windowSize, filter);
183: else
184: getRows(request, sql, windowSize);
185: iterator = getBrowserIterator(request);
186: start = 0;
187: } else {
188: if (sortColName != null) {
189: iterator.sort(sortColName);
190: }
191: }
192:
193: resultSetSize = iterator.getResultSetSize();
194: if (start >= resultSetSize) {
195: if ((start - windowSize) > 0)
196: start = resultSetSize - windowSize;
197: else
198: start = 0;
199: }
200: next = start + windowSize;
201: prev = start - windowSize;
202: if (prev < 0 && start > 0)
203: prev = 0;
204: iterator.setTop(start);
205:
206: readLinkParameters(request, context);
207:
208: if (iterator != null) {
209: resultSetSize = iterator.getResultSetSize();
210:
211: if (next <= resultSetSize) {
212: context.put(NEXT, String.valueOf(next));
213: }
214: if (prev <= resultSetSize && prev >= 0) {
215: context.put(PREVIOUS, String.valueOf(prev));
216: }
217:
218: context.put(BROWSER_ITERATOR, iterator);
219: context.put(BROWSER_TITLE_ITERATOR, iterator
220: .getResultSetTitleList());
221: context.put(BROWSER_TABLE_SIZE, new Integer(
222: resultSetSize));
223: context.put(WINDOW_SIZE, new Integer(windowSize));
224: context.put(START, new Integer(start));
225: /*
226: * System.out.println("buildNormalContext Sort column name=
227: * "+sortColName); System.out.println("buildNormalContext
228: * Iterator: "+iterator); System.out.println("buildNormalContext
229: * Titles= "+iterator.getResultSetTitleList());
230: * System.out.println("buildNormalContext
231: * windowSize="+windowSize+" prev="+prev+ " next="+next+"
232: * start="+start+" resultSetSize="+resultSetSize);
233: */
234: }
235:
236: } catch (Exception e) {
237: String msg = e.toString();
238: Throwable cause = e.getCause();
239: if (cause != null) {
240: msg = msg + ", " + cause.getMessage();
241: }
242:
243: context.put("statusMsg", new StatusMessage(msg,
244: StatusMessage.ERROR));
245: // log the error msg
246: log.error("Exception", e);
247:
248: /*
249: * TODO: error logging
250: *
251: * rundata.setMessage("Error in Portals Gems Browser: " +
252: * e.toString()); rundata.setStackTrace(StringUtils.stackTrace(e),
253: * e);
254: * rundata.setScreenTemplate(JetspeedResources.getString("template.error","Error"));
255: */
256: }
257:
258: super .doView(request, response);
259: }
260:
261: public void doEdit(RenderRequest request, RenderResponse response)
262: throws PortletException, IOException {
263: response.setContentType("text/html");
264: doPreferencesEdit(request, response);
265: }
266:
267: public void processAction(ActionRequest request,
268: ActionResponse response) throws PortletException,
269: IOException {
270: if (request.getPortletMode() == PortletMode.EDIT) {
271: processPreferencesAction(request, response);
272: clearBrowserIterator(request);
273: } else {
274: String browserAction = request
275: .getParameter("db.browser.action");
276: if (browserAction != null) {
277: if (browserAction.equals("refresh")) {
278: clearBrowserIterator(request);
279: }
280: String start = request.getParameter(START);
281: if (start != null) {
282: response.setRenderParameter(START, start);
283: }
284: String searchString = request
285: .getParameter(SEARCH_STRING);
286: if (searchString != null) {
287: String searchColumn = request
288: .getParameter(SEARCH_COLUMN);
289: String filtered = request.getParameter(FILTERED);
290: if (filtered != null) {
291: clearBrowserIterator(request);
292: response.setRenderParameter(FILTER,
293: searchString);
294: } else {
295: int index = find(this
296: .getBrowserIterator(request),
297: searchString, searchColumn);
298: if (index == -1) {
299: try {
300: StatusMessage sm = new StatusMessage(
301: "Could not find match for: "
302: + searchString,
303: StatusMessage.ALERT);
304: PortletMessaging.publish(request,
305: "DatabaseBrowserPortlet",
306: "action", sm);
307: } catch (Exception e) {
308: }
309: } else {
310: response.setRenderParameter(START, Integer
311: .toString(index));
312: }
313: }
314: }
315: }
316: }
317: }
318:
319: /**
320: * Centralizes the calls to session - to retrieve the BrowserIterator.
321: *
322: * @param data
323: * The turbine rundata context for this request.
324: *
325: */
326: protected BrowserIterator getBrowserIterator(PortletRequest request) {
327: BrowserIterator iterator = (BrowserIterator) request
328: .getPortletSession().getAttribute(BROWSER_ACTION_KEY,
329: PortletSession.PORTLET_SCOPE);
330: return iterator;
331: }
332:
333: /**
334: * Centralizes the calls to session - to set the BrowserIterator.
335: *
336: * @param data
337: * The turbine rundata context for this request.
338: * @param iterator.
339: *
340: */
341: protected void setBrowserIterator(RenderRequest request,
342: BrowserIterator iterator) {
343: request.getPortletSession().setAttribute(BROWSER_ACTION_KEY,
344: iterator);
345: }
346:
347: /**
348: * Centralizes the calls to session - to clear the BrowserIterator from the
349: * temp storage.
350: *
351: * @param data
352: * The turbine rundata context for this request.
353: *
354: */
355: protected void clearBrowserIterator(PortletRequest request) {
356: request.getPortletSession().removeAttribute(BROWSER_ACTION_KEY);
357: }
358:
359: protected int getStartVariable(RenderRequest request,
360: String attrName, String sortColName,
361: BrowserIterator iterator) {
362: int start = -1;
363: // if users want to overwrite how the sorting affects the cursor for
364: // the window
365: if (sortColName != null)
366: start = getStartIndex();
367:
368: if (start < 0) {
369: // fallback routine for start
370: String startStr = request.getParameter(attrName);
371: if (startStr != null && startStr.length() > 0) {
372: try {
373: start = Integer.parseInt(startStr);
374: } catch (Exception e) {
375: if (iterator != null)
376: start = iterator.getTop();
377: else
378: start = 0;
379: }
380: } else if (start == -1 && iterator != null) {
381: start = iterator.getTop();
382: }
383:
384: if (start < 0)
385: start = 0;
386: }
387: return start;
388: }
389:
390: /**
391: * to be used if sorting behavior to be overwritten
392: */
393: protected int getStartIndex() {
394: return 0;
395: }
396:
397: /**
398: * This method returns the sql from the getQuery method which can be
399: * overwritten according to the needs of the application. If the getQuery()
400: * returns null, then it gets the value from the psml file. If the psml
401: * value is null then it returns the value from the xreg file.
402: *
403: */
404: protected String getQueryString(RenderRequest request,
405: Context context) {
406: String sql = getQueryString(request);
407: if (null == sql) {
408: sql = getPreference(request, SQL, null);
409: }
410: return sql;
411: }
412:
413: public String getQueryString(RenderRequest request) {
414: return null;
415: }
416:
417: protected String getPreference(RenderRequest request,
418: String attrName, String attrDefValue) {
419: return request.getPreferences()
420: .getValue(attrName, attrDefValue);
421: }
422:
423: protected void readUserParameters(RenderRequest request,
424: Context context) {
425: Object userObjRead = request.getPortletSession().getAttribute(
426: USER_OBJECTS, PortletSession.PORTLET_SCOPE);
427: if (userObjRead != null) {
428: context.put(USER_OBJECTS, userObjRead);
429: // System.out.println("userObjectListSize: "+
430: // ((List)userObjRead).size());
431: } else {
432: /*
433: * TODO: implement user parameters
434: *
435: * String userObjTypes=
436: * getParameterFromRegistry(portlet,USER_OBJECT_TYPES,null); String
437: * userObjNames=
438: * getParameterFromRegistry(portlet,USER_OBJECT_NAMES,null); if(
439: * userObjTypes != null && userObjTypes.length() > 0 ) {
440: * userObjectList = new ArrayList(); int userObjectIndex = 0;
441: * StringTokenizer tokenizer1 = new StringTokenizer(userObjNames,
442: * ","); StringTokenizer tokenizer3 = new
443: * StringTokenizer(userObjTypes, ",");
444: * while(tokenizer1.hasMoreTokens() && tokenizer3.hasMoreTokens()) {
445: * userObjectList.add(userObjectIndex, new
446: * ActionParameter(tokenizer1.nextToken(), null,
447: * tokenizer3.nextToken())); userObjectIndex++; }
448: * context.put(USER_OBJECTS, userObjectList);
449: * setParameterToTemp(portlet, rundata, USER_OBJECTS,
450: * userObjectList); //System.out.println("readLink:
451: * userObjectTypesListSize: "+userObjectList.size()); }
452: */
453: }
454: }
455:
456: protected void readSqlParameters(RenderRequest request) {
457: List sqlParamList = null;
458:
459: int i = 1;
460: while (true) {
461: String param = getPreference(request, SQL_PARAM_PREFIX + i,
462: null);
463: if (param == null) {
464: break;
465: } else {
466: if (sqlParamList == null) {
467: sqlParamList = new ArrayList();
468: }
469: sqlParamList.add(param);
470: }
471: i++;
472: }
473:
474: if (sqlParamList != null) {
475: setSQLParameters(sqlParamList);
476: }
477: }
478:
479: public void setSQLParameters(List parameters) {
480: this .sqlParameters = parameters;
481: }
482:
483: protected void readLinkParameters(RenderRequest request,
484: Context context) {
485: // TODO: implement me
486: }
487:
488: /**
489: * This method should be overwritten every time the user object needs to be
490: * populated with some user specific constraints. As an example if the user
491: * wanted to track the parent of an object based on some calculation per
492: * row, it could be done here.
493: *
494: */
495: public void populate(int rowIndex, int columnIndex, List row) {
496: }
497:
498: /*
499: * (non-Javadoc)
500: *
501: * @see org.apache.jetspeed.modules.actions.portlets.browser.BrowserQuery#filter(java.util.List,
502: * RunData)
503: */
504: public boolean filter(List row, RenderRequest request) {
505: return false;
506: }
507:
508: public void publishStatusMessage(PortletRequest request,
509: String portlet, String topic, Throwable e, String message) {
510: String msg = message + ": " + e.toString();
511: Throwable cause = e.getCause();
512: if (cause != null) {
513: msg = msg + ", " + cause.getMessage();
514: }
515: StatusMessage sm = new StatusMessage(msg, StatusMessage.ERROR);
516: try {
517: // TODO: fixme, bug in Pluto on portlet session
518: PortletMessaging.publish(request, portlet, topic, sm);
519: } catch (Exception ee) {
520: System.err.println("Failed to publish message: " + e);
521: }
522: }
523:
524: public int find(BrowserIterator iterator, String searchString,
525: String searchColumn) {
526: int index = 0;
527: int column = 1;
528:
529: if (searchColumn != null)
530: column = Integer.parseInt(searchColumn);
531:
532: Iterator it = iterator.getResultSet().iterator();
533: while (it.hasNext()) {
534: Object row = it.next();
535: String item = "";
536: if (row instanceof String)
537: item = (String) row;
538: else if (row instanceof List) {
539: // TODO: this only works on String columns
540: item = (String) ((List) row).get(column);
541: }
542: if (item.startsWith(searchString)) {
543: return index;
544: }
545: index++;
546: }
547:
548: return -1;
549: }
550: }
|