001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/search/tags/sakai_2-4-1/search-impl/impl/src/java/org/sakaiproject/search/component/adapter/contenthosting/ContentHostingContentProducer.java $
003: * $Id: ContentHostingContentProducer.java 29179 2007-04-19 02:25:25Z ajpoland@iupui.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2003, 2004, 2005, 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.contenthosting;
021:
022: import java.io.Reader;
023: import java.io.StringReader;
024: import java.util.ArrayList;
025: import java.util.Iterator;
026: import java.util.List;
027: import java.util.Map;
028:
029: import org.apache.commons.logging.Log;
030: import org.apache.commons.logging.LogFactory;
031: import org.sakaiproject.component.api.ComponentManager;
032: import org.sakaiproject.component.cover.ServerConfigurationService;
033: import org.sakaiproject.content.api.ContentHostingService;
034: import org.sakaiproject.content.api.ContentResource;
035: import org.sakaiproject.entity.api.EntityManager;
036: import org.sakaiproject.entity.api.EntityProducer;
037: import org.sakaiproject.entity.api.Reference;
038: import org.sakaiproject.entity.api.ResourceProperties;
039: import org.sakaiproject.event.api.Event;
040: import org.sakaiproject.exception.IdUnusedException;
041: import org.sakaiproject.search.api.EntityContentProducer;
042: import org.sakaiproject.search.api.SearchIndexBuilder;
043: import org.sakaiproject.search.api.SearchService;
044: import org.sakaiproject.search.model.SearchBuilderItem;
045: import org.sakaiproject.site.api.Site;
046: import org.sakaiproject.site.api.SiteService;
047: import org.sakaiproject.site.api.SiteService.SelectionType;
048: import org.sakaiproject.site.api.SiteService.SortType;
049:
050: public class ContentHostingContentProducer implements
051: EntityContentProducer {
052:
053: private static Log log = LogFactory
054: .getLog(ContentHostingContentProducer.class);
055:
056: /**
057: * resolved dep
058: */
059: private SearchService searchService = null;
060:
061: /**
062: * resolved dep
063: */
064: private ContentHostingService contentHostingService = null;
065:
066: /**
067: * resolved dep
068: */
069: private SearchIndexBuilder searchIndexBuilder = null;
070:
071: /**
072: * resolved dep
073: */
074: private EntityManager entityManager = null;
075:
076: /**
077: * resolved dep
078: */
079: private SiteService siteService = null;
080:
081: /**
082: * runtime injected
083: */
084: private ArrayList digesters = new ArrayList();
085:
086: /**
087: * config injected dep
088: */
089: private ContentDigester defaultDigester;
090:
091: private int readerSizeLimit = 1024 * 1024 * 2; // (2M)
092:
093: private int digesterSizeLimit = 1024 * 1024 * 5; // (5M)
094:
095: public void init() {
096: try {
097: ComponentManager cm = org.sakaiproject.component.cover.ComponentManager
098: .getInstance();
099:
100: contentHostingService = (ContentHostingService) load(cm,
101: ContentHostingService.class.getName());
102:
103: searchService = (SearchService) load(cm,
104: SearchService.class.getName());
105: searchIndexBuilder = (SearchIndexBuilder) load(cm,
106: SearchIndexBuilder.class.getName());
107:
108: entityManager = (EntityManager) load(cm,
109: EntityManager.class.getName());
110: siteService = (SiteService) load(cm, SiteService.class
111: .getName());
112:
113: if ("true".equals(ServerConfigurationService.getString(
114: "search.enable", "false"))) {
115:
116: searchService
117: .registerFunction(ContentHostingService.EVENT_RESOURCE_ADD);
118: searchService
119: .registerFunction(ContentHostingService.EVENT_RESOURCE_WRITE);
120: searchService
121: .registerFunction(ContentHostingService.EVENT_RESOURCE_REMOVE);
122: searchIndexBuilder.registerEntityContentProducer(this );
123:
124: }
125:
126: } catch (Throwable t) {
127: log.error("Failed to init Service ", t);
128: }
129:
130: }
131:
132: public void addDigester(ContentDigester digester) {
133: digesters.add(digester);
134: }
135:
136: public void removeDigester(ContentDigester digester) {
137: digesters.remove(digester);
138: }
139:
140: private Object load(ComponentManager cm, String name) {
141: Object o = cm.get(name);
142: if (o == null) {
143: log.error("Cant find Spring component named " + name);
144: }
145: return o;
146: }
147:
148: public boolean isContentFromReader(String ref) {
149: boolean debug = log.isDebugEnabled();
150: ContentResource contentResource;
151: try {
152: Reference reference = entityManager.newReference(ref);
153: contentResource = contentHostingService
154: .getResource(reference.getId());
155: } catch (Exception e) {
156: throw new RuntimeException("Failed to resolve resource "
157: + ref, e);
158: }
159: if (contentResource.getContentLength() > readerSizeLimit) {
160: if (debug) {
161: log.debug("ContentHosting.isContentFromReader" + ref
162: + ":yes");
163: }
164: return true;
165: }
166: if (debug) {
167: log.debug("ContentHosting.isContentFromReader" + ref
168: + ":yes");
169: }
170: return false;
171: }
172:
173: public Reader getContentReader(String ref) {
174: boolean debug = log.isDebugEnabled();
175: ContentResource contentResource;
176: try {
177: Reference reference = entityManager.newReference(ref);
178: contentResource = contentHostingService
179: .getResource(reference.getId());
180: } catch (Exception e) {
181: throw new RuntimeException("Failed to resolve resource "
182: + ref, e);
183: }
184: if (contentResource.getContentLength() <= 0) {
185: if (debug) {
186: log.debug("ContentHosting.getContentReader" + ref
187: + ": empty");
188: }
189: return new StringReader("");
190: }
191:
192: ContentDigester digester = getDigester(contentResource);
193: Reader reader = null;
194: try {
195: reader = digester.getContentReader(contentResource);
196: } catch (Exception ex) {
197: log
198: .debug("Failed to generate content with "
199: + digester, ex);
200: if (!digester.equals(defaultDigester)) {
201: try {
202: reader = defaultDigester
203: .getContentReader(contentResource);
204: } catch (Exception ex2) {
205: log.debug("Failed to extract content from "
206: + contentResource + " using "
207: + defaultDigester, ex2);
208: throw new RuntimeException(
209: "Failed to extract content from "
210: + contentResource + " using "
211: + defaultDigester + " and "
212: + digester, ex);
213: }
214: } else {
215: throw new RuntimeException(
216: "Failed to extract content from "
217: + contentResource + " using "
218: + digester, ex);
219: }
220: }
221: if (debug) {
222: log.debug("ContentHosting.getContentReader" + ref + ":"
223: + reader);
224: }
225: return reader;
226: }
227:
228: public String getContent(String ref) {
229: return getContent(ref, 3);
230: }
231:
232: public String getContent(String ref, int minWordLenght) {
233: boolean debug = log.isDebugEnabled();
234: ContentResource contentResource;
235: try {
236: Reference reference = entityManager.newReference(ref);
237: contentResource = contentHostingService
238: .getResource(reference.getId());
239: } catch (Exception e) {
240: if (debug) {
241: log.debug("Failed To resolve Resource", e);
242: }
243: throw new RuntimeException("Failed to resolve resource ", e);
244: }
245: if (contentResource.getContentLength() <= 0) {
246: if (debug) {
247: log.debug("ContentHosting.getContent" + ref + ":empty");
248: }
249: return "";
250: }
251: ContentDigester digester = getDigester(contentResource);
252: String content = null;
253: try {
254: content = digester.getContent(contentResource);
255: } catch (Exception ex) {
256: log
257: .debug("Failed to generate content with "
258: + digester, ex);
259: if (!digester.equals(defaultDigester)) {
260: try {
261: content = defaultDigester
262: .getContent(contentResource);
263: } catch (Exception ex2) {
264: log.debug("Failed to extract content from "
265: + contentResource + " using "
266: + defaultDigester, ex2);
267: throw new RuntimeException(
268: "Failed to extract content from "
269: + contentResource + " using "
270: + defaultDigester + " and "
271: + digester, ex);
272: }
273: } else {
274: if (debug) {
275: log.debug("Failed To extract content");
276: }
277: throw new RuntimeException(
278: "Failed to extract content from "
279: + contentResource + " using "
280: + digester, ex);
281: }
282: }
283: if (debug) {
284: log
285: .debug("ContentHosting.getContent" + ref + ":"
286: + content);
287: }
288: return content;
289:
290: }
291:
292: public ContentDigester getDigester(ContentResource cr) {
293: boolean debug = log.isDebugEnabled();
294: if (cr.getContentLength() > digesterSizeLimit) {
295: return defaultDigester;
296: }
297: String mimeType = cr.getContentType();
298: for (Iterator i = digesters.iterator(); i.hasNext();) {
299: ContentDigester digester = (ContentDigester) i.next();
300: if (digester.accept(mimeType)) {
301: return digester;
302: }
303: }
304: return defaultDigester;
305:
306: }
307:
308: public String getTitle(String ref) {
309: boolean debug = log.isDebugEnabled();
310: ContentResource contentResource;
311: try {
312: Reference reference = entityManager.newReference(ref);
313: contentResource = contentHostingService
314: .getResource(reference.getId());
315: } catch (Exception e) {
316: if (debug) {
317: log.debug("Failed To resolve Resource", e);
318: }
319:
320: throw new RuntimeException("Failed to resolve resource ", e);
321: }
322: ResourceProperties rp = contentResource.getProperties();
323: String displayNameProp = rp.getNamePropDisplayName();
324: String title = rp.getProperty(displayNameProp);
325: if (debug) {
326: log.debug("ContentHosting.getTitle" + ref + ":" + title);
327: }
328: return title;
329: }
330:
331: public boolean matches(String ref) {
332: boolean debug = log.isDebugEnabled();
333: try {
334: Reference reference = entityManager.newReference(ref);
335: EntityProducer ep = reference.getEntityProducer();
336: boolean m = (ep instanceof ContentHostingService);
337: if (debug) {
338: log.debug("ContentHosting.matches" + ref + ":" + m);
339: }
340: return m;
341:
342: } catch (Exception ex) {
343: if (debug) {
344: log.debug("ContentHosting.matches" + ref
345: + ":fail-no-match");
346: }
347: return false;
348: }
349: }
350:
351: public List getAllContent() {
352: boolean debug = log.isDebugEnabled();
353: List sites = siteService.getSites(SelectionType.ANY, null,
354: null, null, SortType.NONE, null);
355: List l = new ArrayList();
356: for (Iterator is = sites.iterator(); is.hasNext();) {
357: Site s = (Site) is.next();
358: String siteCollection = contentHostingService
359: .getSiteCollection(s.getId());
360: List siteContent = contentHostingService
361: .getAllResources(siteCollection);
362: for (Iterator i = siteContent.iterator(); i.hasNext();) {
363: ContentResource resource = (ContentResource) i.next();
364: l.add(resource.getReference());
365: }
366: }
367: if (debug) {
368: log.debug("ContentHosting.getAllContent::" + l.size());
369: }
370: return l;
371:
372: }
373:
374: public Integer getAction(Event event) {
375: boolean debug = log.isDebugEnabled();
376: String eventName = event.getEvent();
377: if (ContentHostingService.EVENT_RESOURCE_ADD.equals(eventName)
378: || ContentHostingService.EVENT_RESOURCE_WRITE
379: .equals(eventName)) {
380: if (debug) {
381: log.debug("ContentHosting.getAction" + event + ":add");
382: }
383: return SearchBuilderItem.ACTION_ADD;
384: }
385: if (ContentHostingService.EVENT_RESOURCE_REMOVE
386: .equals(eventName)) {
387: if (debug) {
388: log.debug("ContentHosting.getAction" + event
389: + ":delete");
390: }
391: return SearchBuilderItem.ACTION_DELETE;
392: }
393: if (debug) {
394: log.debug("ContentHosting.getAction" + event + ":uknown");
395: }
396: return SearchBuilderItem.ACTION_UNKNOWN;
397: }
398:
399: public boolean matches(Event event) {
400: boolean debug = log.isDebugEnabled();
401: boolean m = !SearchBuilderItem.ACTION_UNKNOWN
402: .equals(getAction(event));
403: if (debug) {
404: log.debug("ContentHosting.matches" + event + ":" + m);
405: }
406: return m;
407: }
408:
409: public String getTool() {
410: return "content";
411: }
412:
413: public String getUrl(String ref) {
414: boolean debug = log.isDebugEnabled();
415: Reference reference = entityManager.newReference(ref);
416: String url = reference.getUrl();
417: if (debug) {
418: log.debug("ContentHosting.getAction" + ref + ":" + url);
419: }
420: return url;
421: }
422:
423: private String getSiteId(Reference ref) {
424: String r = ref.getContext();
425: if (log.isDebugEnabled()) {
426: log.debug("ContentHosting.getSiteId" + ref + ":" + r);
427: }
428: return r;
429: }
430:
431: public String getSiteId(String resourceName) {
432: String r = getSiteId(entityManager.newReference(resourceName));
433: if (log.isDebugEnabled()) {
434: log.debug("ContentHosting.getSiteId" + resourceName + ":"
435: + r);
436: }
437: return r;
438: }
439:
440: public List getSiteContent(String context) {
441: boolean debug = log.isDebugEnabled();
442: String siteCollection = contentHostingService
443: .getSiteCollection(context);
444: List siteContent = contentHostingService
445: .getAllResources(siteCollection);
446: List l = new ArrayList();
447: for (Iterator i = siteContent.iterator(); i.hasNext();) {
448: ContentResource resource = (ContentResource) i.next();
449: l.add(resource.getReference());
450: }
451: if (debug) {
452: log.debug("ContentHosting.getSiteContent" + context + ":"
453: + l.size());
454: }
455: return l;
456: }
457:
458: public Iterator getSiteContentIterator(String context) {
459: boolean debug = log.isDebugEnabled();
460:
461: String siteCollection = contentHostingService
462: .getSiteCollection(context);
463: if (debug) {
464: log
465: .debug("Getting content for site info "
466: + siteCollection);
467: }
468: List siteContent = null;
469: if ("/".equals(siteCollection)) {
470: siteContent = new ArrayList();
471: } else {
472: siteContent = contentHostingService
473: .getAllResources(siteCollection);
474: }
475: final Iterator scIterator = siteContent.iterator();
476: return new Iterator() {
477:
478: public boolean hasNext() {
479: return scIterator.hasNext();
480: }
481:
482: public Object next() {
483: ContentResource resource = (ContentResource) scIterator
484: .next();
485: return resource.getReference();
486: }
487:
488: public void remove() {
489: throw new UnsupportedOperationException(
490: "Remove is not implimented ");
491: }
492:
493: };
494: }
495:
496: /**
497: * @return Returns the readerSizeLimit.
498: */
499: public int getReaderSizeLimit() {
500: return readerSizeLimit;
501: }
502:
503: /**
504: * @param readerSizeLimit
505: * The readerSizeLimit to set.
506: */
507: public void setReaderSizeLimit(int readerSizeLimit) {
508: this .readerSizeLimit = readerSizeLimit;
509: }
510:
511: /**
512: * @return Returns the defaultDigester.
513: */
514: public ContentDigester getDefaultDigester() {
515: return defaultDigester;
516: }
517:
518: /**
519: * @param defaultDigester
520: * The defaultDigester to set.
521: */
522: public void setDefaultDigester(ContentDigester defaultDigester) {
523: this .defaultDigester = defaultDigester;
524: }
525:
526: public boolean isForIndex(String ref) {
527: ContentResource contentResource;
528: try {
529: Reference reference = entityManager.newReference(ref);
530:
531: contentResource = contentHostingService
532: .getResource(reference.getId());
533: } catch (IdUnusedException idun) {
534: if (log.isDebugEnabled()) {
535: log.debug("Resource Not present in CHS " + ref);
536: }
537:
538: return false; // a collection or unknown resource that cant be
539: // indexed
540: } catch (Exception e) {
541: if (log.isDebugEnabled()) {
542: log.debug("Failed To resolve Resource", e);
543: }
544: throw new RuntimeException("Failed to resolve resource ", e);
545: }
546: return true;
547: }
548:
549: public boolean canRead(String ref) {
550: try {
551: Reference reference = entityManager.newReference(ref);
552: contentHostingService.checkResource(reference.getId());
553: return true;
554: } catch (Exception ex) {
555: return false;
556: }
557: }
558:
559: public Map getCustomProperties() {
560: return null;
561: }
562:
563: public String getCustomRDF() {
564: return null;
565: }
566:
567: /**
568: * @return Returns the digesterSizeLimit.
569: */
570: public int getDigesterSizeLimit() {
571: return digesterSizeLimit;
572: }
573:
574: /**
575: * @param digesterSizeLimit
576: * The digesterSizeLimit to set.
577: */
578: public void setDigesterSizeLimit(int digesterSizeLimit) {
579: this .digesterSizeLimit = digesterSizeLimit;
580: }
581:
582: private Reference getReference(String reference) {
583: try {
584: return entityManager.newReference(reference);
585: } catch (Exception ex) {
586: if (log.isDebugEnabled()) {
587: log.debug("Failed To resolve Resource", ex);
588: }
589:
590: }
591: return null;
592: }
593:
594: /* (non-Javadoc)
595: * @see org.sakaiproject.search.api.EntityContentProducer#getId(java.lang.String)
596: */
597: public String getId(String reference) {
598: boolean debug = log.isDebugEnabled();
599: try {
600: return getReference(reference).getId();
601: } catch (Exception ex) {
602: if (debug) {
603: log.debug("Failed To resolve Resource", ex);
604: }
605:
606: return "";
607: }
608: }
609:
610: /* (non-Javadoc)
611: * @see org.sakaiproject.search.api.EntityContentProducer#getSubType(java.lang.String)
612: */
613: public String getSubType(String reference) {
614: boolean debug = log.isDebugEnabled();
615: try {
616: String r = getReference(reference).getSubType();
617: if (debug) {
618: log.debug("ContentHosting.getSubType" + reference + ":"
619: + r);
620: }
621: return r;
622: } catch (Exception ex) {
623: return "";
624: }
625: }
626:
627: /* (non-Javadoc)
628: * @see org.sakaiproject.search.api.EntityContentProducer#getType(java.lang.String)
629: */
630: public String getType(String reference) {
631: boolean debug = log.isDebugEnabled();
632: try {
633: String r = getReference(reference).getType();
634: if (debug) {
635: log.debug("ContentHosting.getType" + reference + ":"
636: + r);
637: }
638: return r;
639: } catch (Exception ex) {
640: return "";
641: }
642: }
643:
644: /* (non-Javadoc)
645: * @see org.sakaiproject.search.api.EntityContentProducer#getType(java.lang.String)
646: */
647: public String getContainer(String reference) {
648: boolean debug = log.isDebugEnabled();
649: try {
650: String r = getReference(reference).getContainer();
651: if (debug) {
652: log.debug("ContentHosting.getContainer" + reference
653: + ":" + r);
654: }
655: return r;
656: } catch (Exception ex) {
657: return "";
658: }
659: }
660:
661: }
|