001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/portal/trunk/portal-impl/impl/src/java/org/sakaiproject/portal/charon/SessionRequestHolder.java $
003: * $Id: SessionRequestHolder.java 14690 2006-09-15 11:43:18Z ian@caret.cam.ac.uk $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.search.component.adapter.message;
021:
022: import java.io.Reader;
023: import java.io.StringReader;
024: import java.lang.reflect.Method;
025: import java.util.ArrayList;
026: import java.util.Iterator;
027: import java.util.List;
028: import java.util.Map;
029:
030: import org.apache.commons.logging.Log;
031: import org.apache.commons.logging.LogFactory;
032: import org.sakaiproject.component.api.ComponentManager;
033: import org.sakaiproject.component.cover.ServerConfigurationService;
034: import org.sakaiproject.entity.api.EntityManager;
035: import org.sakaiproject.entity.api.EntityProducer;
036: import org.sakaiproject.entity.api.Reference;
037: import org.sakaiproject.event.api.Event;
038: import org.sakaiproject.exception.IdUnusedException;
039: import org.sakaiproject.exception.PermissionException;
040: import org.sakaiproject.message.api.Message;
041: import org.sakaiproject.message.api.MessageChannel;
042: import org.sakaiproject.message.api.MessageHeader;
043: import org.sakaiproject.message.api.MessageService;
044: import org.sakaiproject.search.api.EntityContentProducer;
045: import org.sakaiproject.search.api.SearchIndexBuilder;
046: import org.sakaiproject.search.api.SearchService;
047: import org.sakaiproject.search.api.SearchUtils;
048: import org.sakaiproject.search.component.Messages;
049: import org.sakaiproject.search.component.adapter.contenthosting.HTMLParser;
050: import org.sakaiproject.search.model.SearchBuilderItem;
051:
052: /**
053: * @author ieb
054: */
055: public class MessageContentProducer implements EntityContentProducer {
056:
057: /**
058: * debug logger
059: */
060: private static Log log = LogFactory
061: .getLog(MessageContentProducer.class);
062:
063: // runtime dependency
064: private String toolName = null;
065:
066: // runtime dependency
067: private List addEvents = null;
068:
069: // runtime dependency
070: private List removeEvents = null;
071:
072: // injected dependency
073: private MessageService messageService = null;
074:
075: // runtime dependency
076: private SearchService searchService = null;
077:
078: // runtime dependency
079: private SearchIndexBuilder searchIndexBuilder = null;
080:
081: private EntityManager entityManager = null;
082:
083: public void init() {
084: ComponentManager cm = org.sakaiproject.component.cover.ComponentManager
085: .getInstance();
086:
087: searchService = (SearchService) load(cm, SearchService.class
088: .getName());
089: searchIndexBuilder = (SearchIndexBuilder) load(cm,
090: SearchIndexBuilder.class.getName());
091:
092: entityManager = (EntityManager) load(cm, EntityManager.class
093: .getName());
094:
095: if ("true".equals(ServerConfigurationService.getString(
096: "search.enable", "false"))) {
097: for (Iterator i = addEvents.iterator(); i.hasNext();) {
098: searchService.registerFunction((String) i.next());
099: }
100: for (Iterator i = removeEvents.iterator(); i.hasNext();) {
101: searchService.registerFunction((String) i.next());
102: }
103: searchIndexBuilder.registerEntityContentProducer(this );
104: }
105: }
106:
107: private Object load(ComponentManager cm, String name) {
108: Object o = cm.get(name);
109: if (o == null) {
110: log.error("Cant find Spring component named " + name); //$NON-NLS-1$
111: }
112: return o;
113: }
114:
115: /**
116: * {@inheritDoc}
117: */
118: public boolean isContentFromReader(String reference) {
119: return false;
120: }
121:
122: /**
123: * {@inheritDoc}
124: */
125: public Reader getContentReader(String reference) {
126: return new StringReader(getContent(reference));
127: }
128:
129: private Reference getReference(String reference) {
130: try {
131: Reference r = entityManager.newReference(reference);
132: if (log.isDebugEnabled()) {
133: log.debug("Message." + toolName + ".getReference"
134: + reference + ":" + r);
135: }
136: return r;
137: } catch (Exception ex) {
138: }
139: return null;
140: }
141:
142: private EntityProducer getProducer(Reference ref) {
143: try {
144: return ref.getEntityProducer();
145: } catch (Exception ex) {
146: }
147: return null;
148: }
149:
150: /**
151: * {@inheritDoc}
152: */
153: public String getContent(String reference) {
154: Reference ref = getReference(reference);
155: EntityProducer ep = getProducer(ref);
156:
157: if (ep instanceof MessageService) {
158: try {
159: MessageService ms = (MessageService) ep;
160: Message m = ms.getMessage(ref);
161: MessageHeader mh = m.getHeader();
162: StringBuilder sb = new StringBuilder();
163: Class c = mh.getClass();
164: try {
165: Method getSubject = c.getMethod("getSubject", //$NON-NLS-1$
166: new Class[] {});
167: Object o = getSubject.invoke(mh, new Object[] {});
168: sb.append(Messages
169: .getString("MessageContentProducer.5"));
170: SearchUtils.appendCleanString(o.toString(), sb);
171: sb.append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
172: } catch (Exception ex) {
173: // no subject, and I dont mind
174: log.debug("Didnt get Subject from " + mh, ex); //$NON-NLS-1$
175: }
176:
177: sb.append(Messages
178: .getString("MessageContentProducer.3")); //$NON-NLS-1$
179: sb.append(Messages
180: .getString("MessageContentProducer.4"));
181: SearchUtils.appendCleanString(mh.getFrom()
182: .getDisplayName(), sb); //$NON-NLS-1$
183: sb.append("\n"); //$NON-NLS-1$
184: sb.append(Messages
185: .getString("MessageContentProducer.11")); //$NON-NLS-1$
186: String mBody = m.getBody();
187:
188: for (HTMLParser hp = new HTMLParser(mBody); hp
189: .hasNext();) {
190: SearchUtils.appendCleanString(hp.next(), sb);
191: sb.append(" ");
192: }
193:
194: sb.append("\n"); //$NON-NLS-1$
195: log
196: .debug("Message Content for " + ref.getReference() + " is " //$NON-NLS-1$ //$NON-NLS-2$
197: + sb.toString());
198:
199: // resolve attachments
200: List attachments = mh.getAttachments();
201: for (Iterator atti = attachments.iterator(); atti
202: .hasNext();) {
203: try {
204: Reference attr = (Reference) atti.next();
205: String areference = attr.getReference();
206: EntityContentProducer ecp = searchIndexBuilder
207: .newEntityContentProducer(areference);
208: String attachementDigest = ecp
209: .getContent(areference);
210: sb
211: .append(
212: Messages
213: .getString("MessageContentProducer.23")).append(attachementDigest) //$NON-NLS-1$
214: .append("\n"); //$NON-NLS-1$
215: } catch (Exception ex) {
216: log.info(" Failed to digest attachement " //$NON-NLS-1$
217: + ex.getMessage());
218: }
219: }
220: String r = sb.toString();
221: if (log.isDebugEnabled()) {
222: log.debug("Message." + toolName + ".getContent"
223: + reference + ":" + r);
224: }
225: return r;
226: } catch (IdUnusedException e) {
227: throw new RuntimeException(
228: " Failed to get message content ", e); //$NON-NLS-1$
229: } catch (PermissionException e) {
230: throw new RuntimeException(
231: " Failed to get message content ", e); //$NON-NLS-1$
232: }
233: }
234:
235: throw new RuntimeException(" Not a Message Entity " + reference); //$NON-NLS-1$
236: }
237:
238: /**
239: * @{inheritDoc}
240: */
241: public String getTitle(String reference) {
242: Reference ref = getReference(reference);
243: EntityProducer ep = getProducer(ref);
244: if (ep instanceof MessageService) {
245: try {
246: MessageService ms = (MessageService) ep;
247: Message m = ms.getMessage(ref);
248: MessageHeader mh = m.getHeader();
249: Class c = mh.getClass();
250: String subject = Messages
251: .getString("MessageContentProducer.2"); //$NON-NLS-1$
252: try {
253: Method getSubject = c.getMethod("getSubject", //$NON-NLS-1$
254: new Class[] {});
255: Object o = getSubject.invoke(mh, new Object[] {});
256: subject = Messages
257: .getString("MessageContentProducer.33") + o.toString() + " "; //$NON-NLS-1$ //$NON-NLS-2$
258: } catch (Exception ex) {
259: log.debug("Didnt get Subject from " + mh); //$NON-NLS-1$
260: }
261:
262: String title = subject
263: + Messages
264: .getString("MessageContentProducer.36") //$NON-NLS-1$
265: + mh.getFrom().getDisplayName();
266:
267: String r = SearchUtils.appendCleanString(title, null)
268: .toString();
269: if (log.isDebugEnabled()) {
270: log.debug("Message." + toolName + ".getTitle"
271: + reference + ":" + r);
272: }
273: return r;
274: } catch (IdUnusedException e) {
275: throw new RuntimeException(
276: " Failed to get message content ", e); //$NON-NLS-1$
277: } catch (PermissionException e) {
278: throw new RuntimeException(
279: " Failed to get message content ", e); //$NON-NLS-1$
280: }
281: }
282: throw new RuntimeException(" Not a Message Entity " + reference); //$NON-NLS-1$
283:
284: }
285:
286: /**
287: * @{inheritDoc}
288: */
289: public String getUrl(String reference) {
290: Reference ref = getReference(reference);
291: return ref.getUrl();
292: }
293:
294: /**
295: * @{inheritDoc}
296: */
297: public boolean matches(String reference) {
298: Reference ref = getReference(reference);
299: EntityProducer ep = getProducer(ref);
300:
301: if (ep.getClass().equals(messageService.getClass())) {
302: return true;
303: }
304: return false;
305: }
306:
307: /**
308: * @{inheritDoc}
309: */
310: public List getAllContent() {
311: List all = new ArrayList();
312: List l = messageService.getChannels();
313: for (Iterator i = l.iterator(); i.hasNext();) {
314:
315: try {
316: MessageChannel c = (MessageChannel) i.next();
317:
318: List messages = c.getMessages(null, true);
319: // WARNING: I think the implementation caches on thread, if this
320: // is
321: // a builder
322: // thread this may not work
323: for (Iterator mi = messages.iterator(); mi.hasNext();) {
324: Message m = (Message) mi.next();
325: all.add(m.getReference());
326: }
327: } catch (Exception ex) {
328: log.error("Got error on channel ", ex); //$NON-NLS-1$
329:
330: }
331: }
332: if (log.isDebugEnabled()) {
333: log.debug("Message." + toolName + ".getAllContent::"
334: + all.size());
335: }
336: return all;
337: }
338:
339: /**
340: * @{inheritDoc}
341: */
342: public Integer getAction(Event event) {
343: String evt = event.getEvent();
344: if (evt == null)
345: return SearchBuilderItem.ACTION_UNKNOWN;
346: for (Iterator i = addEvents.iterator(); i.hasNext();) {
347: String match = (String) i.next();
348: if (evt.equals(match)) {
349: return SearchBuilderItem.ACTION_ADD;
350: }
351: }
352: for (Iterator i = removeEvents.iterator(); i.hasNext();) {
353: String match = (String) i.next();
354: if (evt.equals(match)) {
355: return SearchBuilderItem.ACTION_DELETE;
356: }
357: }
358: return SearchBuilderItem.ACTION_UNKNOWN;
359: }
360:
361: /**
362: * @{inheritDoc}
363: */
364: public boolean matches(Event event) {
365: return matches(event.getResource());
366: }
367:
368: /**
369: * @{inheritDoc}
370: */
371: public String getTool() {
372: return toolName;
373: }
374:
375: /**
376: * @return Returns the addEvents.
377: */
378: public List getAddEvents() {
379: return addEvents;
380: }
381:
382: /**
383: * @param addEvents
384: * The addEvents to set.
385: */
386: public void setAddEvents(List addEvents) {
387: this .addEvents = addEvents;
388: }
389:
390: /**
391: * @return Returns the messageService.
392: */
393: public MessageService getMessageService() {
394: return messageService;
395: }
396:
397: /**
398: * @param messageService
399: * The messageService to set.
400: */
401: public void setMessageService(MessageService messageService) {
402: this .messageService = messageService;
403: }
404:
405: /**
406: * @return Returns the toolName.
407: */
408: public String getToolName() {
409: return toolName;
410: }
411:
412: /**
413: * @param toolName
414: * The toolName to set.
415: */
416: public void setToolName(String toolName) {
417: this .toolName = toolName;
418: }
419:
420: /**
421: * @return Returns the removeEvents.
422: */
423: public List getRemoveEvents() {
424: return removeEvents;
425: }
426:
427: /**
428: * @param removeEvents
429: * The removeEvents to set.
430: */
431: public void setRemoveEvents(List removeEvents) {
432: this .removeEvents = removeEvents;
433: }
434:
435: private String getSiteId(Reference ref) {
436: return ref.getContext();
437: }
438:
439: public String getSiteId(String resourceName) {
440:
441: return getSiteId(entityManager.newReference(resourceName));
442: }
443:
444: public List getSiteContent(String context) {
445: List all = new ArrayList();
446: List l = messageService.getChannelIds(context);
447: for (Iterator i = l.iterator(); i.hasNext();) {
448: String chanellId = (String) i.next();
449: try {
450:
451: MessageChannel c = messageService
452: .getChannel(messageService.channelReference(
453: context, chanellId));
454:
455: List messages = c.getMessages(null, true);
456: // WARNING: I think the implementation caches on thread, if this
457: // is
458: // a builder
459: // thread this may not work
460: for (Iterator mi = messages.iterator(); mi.hasNext();) {
461: Message m = (Message) mi.next();
462: all.add(m.getReference());
463: }
464: } catch (Exception ex) {
465: ex.printStackTrace();
466: log.warn("Failed to get channel " + chanellId); //$NON-NLS-1$
467:
468: }
469: }
470: return all;
471: }
472:
473: public Iterator getSiteContentIterator(final String context) {
474: List l = messageService.getChannelIds(context);
475: final Iterator ci = l.iterator();
476: return new Iterator() {
477: Iterator mi = null;
478:
479: public boolean hasNext() {
480: if (mi == null) {
481: return nextIterator();
482: } else {
483: if (mi.hasNext()) {
484: return true;
485: } else {
486: return nextIterator();
487: }
488: }
489: }
490:
491: private boolean nextIterator() {
492: while (ci.hasNext()) {
493:
494: String chanellId = (String) ci.next();
495: try {
496: MessageChannel c = messageService
497: .getChannel(messageService
498: .channelReference(context,
499: chanellId));
500: List messages = c.getMessages(null, true);
501: mi = messages.iterator();
502: if (mi.hasNext()) {
503: return true;
504: }
505: } catch (Exception ex) {
506: ex.printStackTrace();
507: log.warn("Failed to get channel " + chanellId); //$NON-NLS-1$
508:
509: }
510: }
511: return false;
512: }
513:
514: public Object next() {
515: Message m = (Message) mi.next();
516: return m.getReference();
517: }
518:
519: public void remove() {
520: throw new UnsupportedOperationException(
521: "Remove not implemented"); //$NON-NLS-1$
522: }
523:
524: };
525: }
526:
527: public boolean isForIndex(String reference) {
528:
529: Reference ref = getReference(reference);
530: EntityProducer ep = getProducer(ref);
531: if (ep instanceof MessageService) {
532: try {
533: MessageService ms = (MessageService) ep;
534: Message m = ms.getMessage(ref);
535: if (m == null) {
536: log
537: .debug("Rejected null message " + ref.getReference()); //$NON-NLS-1$
538: return false;
539: }
540: } catch (IdUnusedException e) {
541: log.debug("Rejected Missing message or Collection " //$NON-NLS-1$
542: + ref.getReference());
543: return false;
544: } catch (PermissionException e) {
545: log
546: .warn("Rejected private message " + ref.getReference()); //$NON-NLS-1$
547: return false;
548: }
549: return true;
550: }
551: return false;
552: }
553:
554: public boolean canRead(String reference) {
555: Reference ref = getReference(reference);
556: EntityProducer ep = getProducer(ref);
557: if (ep instanceof MessageService) {
558: try {
559: MessageService ms = (MessageService) ep;
560: ms.getMessage(ref);
561: return true;
562: } catch (Exception ex) {
563: }
564: }
565: return false;
566: }
567:
568: public Map getCustomProperties() {
569: return null;
570: }
571:
572: public String getCustomRDF() {
573: return null;
574: }
575:
576: /* (non-Javadoc)
577: * @see org.sakaiproject.search.api.EntityContentProducer#getId(java.lang.String)
578: */
579: public String getId(String reference) {
580: try {
581: String r = getReference(reference).getId();
582: if (log.isDebugEnabled()) {
583: log.debug("Message." + toolName + ".getContainer"
584: + reference + ":" + r);
585: }
586: return r;
587: } catch (Exception ex) {
588: return "";
589: }
590: }
591:
592: /* (non-Javadoc)
593: * @see org.sakaiproject.search.api.EntityContentProducer#getSubType(java.lang.String)
594: */
595: public String getSubType(String reference) {
596: try {
597: String r = getReference(reference).getSubType();
598: if (log.isDebugEnabled()) {
599: log.debug("Message." + toolName + ".getContainer"
600: + reference + ":" + r);
601: }
602: return r;
603: } catch (Exception ex) {
604: return "";
605: }
606: }
607:
608: /* (non-Javadoc)
609: * @see org.sakaiproject.search.api.EntityContentProducer#getType(java.lang.String)
610: */
611: public String getType(String reference) {
612: try {
613: String r = getReference(reference).getType();
614: if (log.isDebugEnabled()) {
615: log.debug("Message." + toolName + ".getContainer"
616: + reference + ":" + r);
617: }
618: return r;
619: } catch (Exception ex) {
620: return "";
621: }
622: }
623:
624: /* (non-Javadoc)
625: * @see org.sakaiproject.search.api.EntityContentProducer#getType(java.lang.String)
626: */
627: public String getContainer(String reference) {
628: try {
629: String r = getReference(reference).getContainer();
630: if (log.isDebugEnabled()) {
631: log.debug("Message." + toolName + ".getContainer"
632: + reference + ":" + r);
633: }
634: return r;
635: } catch (Exception ex) {
636: return "";
637: }
638: }
639:
640: }
|