diff --git a/dspace/modules/additions/src/main/java/org/dspace/app/util/SyndicationFeed.java b/dspace/modules/additions/src/main/java/org/dspace/app/util/SyndicationFeed.java new file mode 100644 index 0000000000000000000000000000000000000000..22f2e21056efd0530462db088c791f1b03f5c32a --- /dev/null +++ b/dspace/modules/additions/src/main/java/org/dspace/app/util/SyndicationFeed.java @@ -0,0 +1,611 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.app.util; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; +import org.w3c.dom.Document; + +import org.dspace.content.Bitstream; +import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.DCDate; +import org.dspace.content.DCValue; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Constants; +import org.dspace.core.Context; +import org.dspace.handle.HandleManager; + +import com.sun.syndication.feed.synd.SyndFeed; +import com.sun.syndication.feed.synd.SyndFeedImpl; +import com.sun.syndication.feed.synd.SyndEntry; +import com.sun.syndication.feed.synd.SyndEntryImpl; +import com.sun.syndication.feed.synd.SyndEnclosure; +import com.sun.syndication.feed.synd.SyndEnclosureImpl; +import com.sun.syndication.feed.synd.SyndImage; +import com.sun.syndication.feed.synd.SyndImageImpl; +import com.sun.syndication.feed.synd.SyndPerson; +import com.sun.syndication.feed.synd.SyndPersonImpl; +import com.sun.syndication.feed.synd.SyndContent; +import com.sun.syndication.feed.synd.SyndContentImpl; +import com.sun.syndication.feed.module.DCModuleImpl; +import com.sun.syndication.feed.module.DCModule; +import com.sun.syndication.feed.module.Module; +import com.sun.syndication.feed.module.itunes.*; +import com.sun.syndication.feed.module.itunes.types.Duration; +import com.sun.syndication.io.SyndFeedOutput; +import com.sun.syndication.io.FeedException; + +import org.apache.log4j.Logger; +import org.dspace.content.Bundle; + +import org.dspace.content.Thumbnail; +import org.dspace.content.service.ItemService; + +/** + * Invoke ROME library to assemble a generic model of a syndication + * for the given list of Items and scope. Consults configuration for the + * metadata bindings to feed elements. Uses ROME's output drivers to + * return any of the implemented formats, e.g. RSS 1.0, RSS 2.0, ATOM 1.0. + * + * The feed generator and OpenSearch call on this class so feed contents are + * uniform for both. + * + * @author Larry Stone + */ +public class SyndicationFeed +{ + private static final Logger log = Logger.getLogger(SyndicationFeed.class); + + + /** i18n key values */ + public static final String MSG_UNTITLED = "notitle"; + public static final String MSG_LOGO_TITLE = "logo.title"; + public static final String MSG_FEED_TITLE = "feed.title"; + public static final String MSG_FEED_DESCRIPTION = "general-feed.description"; + public static final String MSG_METADATA = "metadata."; + public static final String MSG_UITYPE = "ui.type"; + + // UI keywords + public static final String UITYPE_XMLUI = "xmlui"; + public static final String UITYPE_JSPUI = "jspui"; + + // default DC fields for entry + private static String defaultTitleField = "dc.title"; + private static String defaultAuthorField = "dc.contributor.author"; + private static String defaultDateField = "dc.date.issued"; + private static String defaultDescriptionFields = "dc.description.abstract, dc.description, dc.title.alternative, dc.title"; + private static String defaultExternalMedia = "dc.source.uri"; + + // metadata field for Item title in entry: + private static String titleField = + getDefaultedConfiguration("webui.feed.item.title", defaultTitleField); + + // metadata field for Item publication date in entry: + private static String dateField = + getDefaultedConfiguration("webui.feed.item.date", defaultDateField); + + // metadata field for Item description in entry: + private static String descriptionFields[] = + getDefaultedConfiguration("webui.feed.item.description", defaultDescriptionFields).split("\\s*,\\s*"); + + private static String authorField = + getDefaultedConfiguration("webui.feed.item.author", defaultAuthorField); + + // metadata field for Podcast external media source url + private static String externalSourceField = getDefaultedConfiguration("webui.feed.podcast.sourceuri", defaultExternalMedia); + + // metadata field for Item dc:creator field in entry's DCModule (no default) + private static String dcCreatorField = ConfigurationManager.getProperty("webui.feed.item.dc.creator"); + + // metadata field for Item dc:date field in entry's DCModule (no default) + private static String dcDateField = ConfigurationManager.getProperty("webui.feed.item.dc.date"); + + // metadata field for Item dc:author field in entry's DCModule (no default) + private static String dcDescriptionField = ConfigurationManager.getProperty("webui.feed.item.dc.description"); + + // List of available mimetypes that we'll add to podcast feed. Multiple values separated by commas + private static String podcastableMIMETypes = getDefaultedConfiguration("webui.feed.podcast.mimetypes", "audio/x-mpeg"); + + // -------- Instance variables: + + // the feed object we are building + private SyndFeed feed = null; + + // memory of UI that called us, "xmlui" or "jspui" + // affects Bitstream retrieval URL and I18N keys + private String uiType = null; + + private HttpServletRequest request = null; + + /** + * Constructor. + * @param ui either "xmlui" or "jspui" + */ + public SyndicationFeed(String ui) + { + feed = new SyndFeedImpl(); + uiType = ui; + } + + /** + * Returns list of metadata selectors used to compose the description element + * + * @return selector list - format 'schema.element[.qualifier]' + */ + public static String[] getDescriptionSelectors() + { + return (String[]) ArrayUtils.clone(descriptionFields); + } + + + /** + * Fills in the feed and entry-level metadata from DSpace objects. + */ + public void populate(HttpServletRequest request, DSpaceObject dso, + DSpaceObject items[], Map<String, String> labels) + { + String logoURL = null; + String objectURL = null; + String thumbnailURL = null; + String defaultTitle = null; + boolean podcastFeed = false; + this.request = request; + + // dso is null for the whole site, or a search without scope + if (dso == null) + { + defaultTitle = ConfigurationManager.getProperty("dspace.name"); + feed.setDescription(localize(labels, MSG_FEED_DESCRIPTION)); + objectURL = resolveURL(request, null); + logoURL = ConfigurationManager.getProperty("webui.feed.logo.url"); + } + else + { + Bitstream logo = null; + if (dso.getType() == Constants.COLLECTION) + { + Collection col = (Collection)dso; + defaultTitle = col.getMetadata("name"); + feed.setDescription(col.getMetadata("short_description")); + logo = col.getLogo(); + String cols = ConfigurationManager.getProperty("webui.feed.podcast.collections"); + if(cols != null && cols.length() > 1 && cols.contains(col.getHandle()) ) { + podcastFeed = true; + } + } + else if (dso.getType() == Constants.COMMUNITY) + { + Community comm = (Community)dso; + defaultTitle = comm.getMetadata("name"); + feed.setDescription(comm.getMetadata("short_description")); + logo = comm.getLogo(); + String comms = ConfigurationManager.getProperty("webui.feed.podcast.communities"); + if(comms != null && comms.length() > 1 && comms.contains(comm.getHandle()) ){ + podcastFeed = true; + } + } + objectURL = resolveURL(request, dso); + if (logo != null) + { + logoURL = urlOfBitstream(request, logo); + } + } + feed.setTitle(labels.containsKey(MSG_FEED_TITLE) ? + localize(labels, MSG_FEED_TITLE) : defaultTitle); + feed.setLink(objectURL); + feed.setPublishedDate(new Date()); + feed.setUri(objectURL); + + // add logo if we found one: + if (logoURL != null) + { + // we use the path to the logo for this, the logo itself cannot + // be contained in the rdf. Not all RSS-viewers show this logo. + SyndImage image = new SyndImageImpl(); + image.setLink(objectURL); + if (StringUtils.isNotBlank(feed.getTitle())) { + image.setTitle(feed.getTitle()); + } else { + image.setTitle(localize(labels, MSG_LOGO_TITLE)); + } + image.setUrl(logoURL); + feed.setImage(image); + } + + // add entries for items + if (items != null) + { + List<SyndEntry> entries = new ArrayList<SyndEntry>(); + for (DSpaceObject itemDSO : items) + { + if (itemDSO.getType() != Constants.ITEM) + { + continue; + } + Item item = (Item)itemDSO; + boolean hasDate = false; + SyndEntry entry = new SyndEntryImpl(); + entries.add(entry); + + String entryURL = resolveURL(request, item); + entry.setLink(entryURL); + entry.setUri(entryURL); + + String title = getOneDC(item, titleField); + entry.setTitle(title == null ? localize(labels, MSG_UNTITLED) : title); + + // "published" date -- should be dc.date.issued + String pubDate = getOneDC(item, dateField); + if (pubDate != null) + { + entry.setPublishedDate((new DCDate(pubDate)).toDate()); + hasDate = true; + } + // date of last change to Item + entry.setUpdatedDate(item.getLastModified()); + + //create StringBuffer to store item's description + StringBuffer db = new StringBuffer(); + + //add item's thumbnail at begin of description + thumbnailURL = urlOfItemThumbnail(request, item); + if (thumbnailURL != null) + { + db.append("<img src=\""+thumbnailURL+"\" >"); + } + + //populate item's description + for (String df : descriptionFields) + { + // Special Case: "(date)" in field name means render as date + boolean isDate = df.indexOf("(date)") > 0; + if (isDate) + { + df = df.replaceAll("\\(date\\)", ""); + } + + DCValue dcv[] = item.getMetadata(df); + if (dcv.length > 0) + { + String fieldLabel = labels.get(MSG_METADATA + df); + if (fieldLabel != null && fieldLabel.length()>0) + { + db.append(fieldLabel).append(": "); + } + boolean first = true; + for (DCValue v : dcv) + { + if (first) + { + first = false; + } + else + { + db.append("; "); + } + db.append(isDate ? new DCDate(v.value).toString() : v.value); + } + db.append("\n"); + } + } + if (db.length() > 0) + { + SyndContent desc = new SyndContentImpl(); + desc.setType("text/plain"); + desc.setValue(db.toString()); + entry.setDescription(desc); + } + + // This gets the authors into an ATOM feed + DCValue authors[] = item.getMetadata(authorField); + if (authors.length > 0) + { + List<SyndPerson> creators = new ArrayList<SyndPerson>(); + for (DCValue author : authors) + { + SyndPerson sp = new SyndPersonImpl(); + sp.setName(author.value); + creators.add(sp); + } + entry.setAuthors(creators); + } + + // only add DC module if any DC fields are configured + if (dcCreatorField != null || dcDateField != null || + dcDescriptionField != null) + { + DCModule dc = new DCModuleImpl(); + if (dcCreatorField != null) + { + DCValue dcAuthors[] = item.getMetadata(dcCreatorField); + if (dcAuthors.length > 0) + { + List<String> creators = new ArrayList<String>(); + for (DCValue author : dcAuthors) + { + creators.add(author.value); + } + dc.setCreators(creators); + } + } + if (dcDateField != null && !hasDate) + { + DCValue v[] = item.getMetadata(dcDateField); + if (v.length > 0) + { + dc.setDate((new DCDate(v[0].value)).toDate()); + } + } + if (dcDescriptionField != null) + { + DCValue v[] = item.getMetadata(dcDescriptionField); + if (v.length > 0) + { + StringBuffer descs = new StringBuffer(); + for (DCValue d : v) + { + if (descs.length() > 0) + { + descs.append("\n\n"); + } + descs.append(d.value); + } + dc.setDescription(descs.toString()); + } + } + entry.getModules().add(dc); + } + + //iTunes Podcast Support - START + if (podcastFeed) + { + // Add enclosure(s) + List<SyndEnclosure> enclosures = new ArrayList(); + try { + Bundle[] bunds = item.getBundles("ORIGINAL"); + if (bunds[0] != null) { + Bitstream[] bits = bunds[0].getBitstreams(); + for (int i = 0; (i < bits.length); i++) { + String mime = bits[i].getFormat().getMIMEType(); + if(podcastableMIMETypes.contains(mime)) { + SyndEnclosure enc = new SyndEnclosureImpl(); + enc.setType(bits[i].getFormat().getMIMEType()); + enc.setLength(bits[i].getSize()); + enc.setUrl(urlOfBitstream(request, bits[i])); + enclosures.add(enc); + } else { + continue; + } + } + } + //Also try to add an external value from dc.identifier.other + // We are assuming that if this is set, then it is a media file + DCValue[] externalMedia = item.getMetadata(externalSourceField); + if(externalMedia.length > 0) + { + for(int i = 0; i< externalMedia.length; i++) + { + SyndEnclosure enc = new SyndEnclosureImpl(); + enc.setType("audio/x-mpeg"); //We can't determine MIME of external file, so just picking one. + enc.setLength(1); + enc.setUrl(externalMedia[i].value); + enclosures.add(enc); + } + } + + } catch (Exception e) { + System.out.println(e.getMessage()); + } + entry.setEnclosures(enclosures); + + // Get iTunes specific fields: author, subtitle, summary, duration, keywords + EntryInformation itunes = new EntryInformationImpl(); + + String author = getOneDC(item, authorField); + if (author != null && author.length() > 0) { + itunes.setAuthor(author); // <itunes:author> + } + + itunes.setSubtitle(title == null ? localize(labels, MSG_UNTITLED) : title); // <itunes:subtitle> + + if (db.length() > 0) { + itunes.setSummary(db.toString()); // <itunes:summary> + } + + String extent = getOneDC(item, "dc.format.extent"); // assumed that user will enter this field with length of song in seconds + if (extent != null && extent.length() > 0) { + extent = extent.split(" ")[0]; + Integer duration = Integer.parseInt(extent); + itunes.setDuration(new Duration(duration)); // <itunes:duration> + } + + String subject = getOneDC(item, "dc.subject"); + if (subject != null && subject.length() > 0) { + String[] subjects = new String[1]; + subjects[0] = subject; + itunes.setKeywords(subjects); // <itunes:keywords> + } + + entry.getModules().add(itunes); + } + } + feed.setEntries(entries); + } + } + + /** + * Sets the feed type for XML delivery, e.g. "rss_1.0", "atom_1.0" + * Must match one of ROME's configured generators, see rome.properties + * (currently rss_1.0, rss_2.0, atom_1.0, atom_0.3) + */ + public void setType(String feedType) + { + feed.setFeedType(feedType); + // XXX FIXME: workaround ROME 1.0 bug, it puts invalid image element in rss1.0 + if ("rss_1.0".equals(feedType)) + { + feed.setImage(null); + } + } + + /** + * @return the feed we built as DOM Document + */ + public Document outputW3CDom() + throws FeedException + { + try + { + SyndFeedOutput feedWriter = new SyndFeedOutput(); + return feedWriter.outputW3CDom(feed); + } + catch (FeedException e) + { + log.error(e); + throw e; + } + } + + /** + * @return the feed we built as serialized XML string + */ + public String outputString() + throws FeedException + { + SyndFeedOutput feedWriter = new SyndFeedOutput(); + return feedWriter.outputString(feed); + } + + /** + * send the output to designated Writer + */ + public void output(java.io.Writer writer) + throws FeedException, IOException + { + SyndFeedOutput feedWriter = new SyndFeedOutput(); + feedWriter.output(feed, writer); + } + + /** + * Add a ROME plugin module (e.g. for OpenSearch) at the feed level. + */ + public void addModule(Module m) + { + feed.getModules().add(m); + } + + // utility to get config property with default value when not set. + private static String getDefaultedConfiguration(String key, String dfl) + { + String result = ConfigurationManager.getProperty(key); + return (result == null) ? dfl : result; + } + + // returns absolute URL to download content of bitstream (which might not belong to any Item) + private String urlOfBitstream(HttpServletRequest request, Bitstream logo) + { + String name = logo.getName(); + return resolveURL(request,null) + + (uiType.equalsIgnoreCase(UITYPE_XMLUI) ?"/bitstream/id/":"/retrieve/") + + logo.getID()+"/"+(name == null?"":name); + } + + //returns absolute URL of Item's Thumbnail + private String urlOfItemThumbnail(HttpServletRequest request, Item item){ + try + { + Thumbnail thumbnail = ItemService.getThumbnail(new Context(), item.getID(), false); + if (thumbnail != null) + { + return urlOfBitstream(request, thumbnail.getThumb()); + } + else + { + return null; + } + } + catch (SQLException e) + { + log.error("caught exception: ", e); + return null; + } + } + + /** + * Return a url to the DSpace object, either use the official + * handle for the item or build a url based upon the current server. + * + * If the dspaceobject is null then a local url to the repository is generated. + * + * @param dso The object to reference, null if to the repository. + * @return + */ + private String baseURL = null; // cache the result for null + + private String resolveURL(HttpServletRequest request, DSpaceObject dso) + { + // If no object given then just link to the whole repository, + // since no offical handle exists so we have to use local resolution. + if (dso == null) + { + if (baseURL == null) + { + if (request == null) + { + baseURL = ConfigurationManager.getProperty("dspace.url"); + } + else + { + baseURL = (request.isSecure()) ? "https://" : "http://"; + baseURL += ConfigurationManager.getProperty("dspace.hostname"); + baseURL += ":" + request.getServerPort(); + baseURL += request.getContextPath(); + } + } + return baseURL; + } + + // return a link to handle in repository + else if (ConfigurationManager.getBooleanProperty("webui.feed.localresolve")) + { + return resolveURL(request, null) + "/handle/" + dso.getHandle(); + } + + // link to the Handle server or other persistent URL source + else + { + return HandleManager.getCanonicalForm(dso.getHandle()); + } + } + + // retrieve text for localization key, or mark untranslated + private String localize(Map<String, String> labels, String s) + { + return labels.containsKey(s) ? labels.get(s) : ("Untranslated:"+s); + } + + // spoonful of syntactic sugar when we only need first value + private String getOneDC(Item item, String field) + { + DCValue dcv[] = item.getMetadata(field); + return (dcv.length > 0) ? dcv[0].value : null; + } +} + diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio-mobile/lib/m-tweaks.css b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio-mobile/lib/m-tweaks.css index 741b73edc35e51687d203d0264ad95a7bb390fb7..d7227515c624f60ccbdbc0ed09e1ee8e059b2be4 100644 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio-mobile/lib/m-tweaks.css +++ b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio-mobile/lib/m-tweaks.css @@ -525,3 +525,37 @@ clear: both; width: 100% } +div#aspect_artifactbrowser_CommunityBrowser_div_comunity-browser a { + padding: 0px !important; +} + +div#aspect_artifactbrowser_CommunityBrowser_div_comunity-browser img { + width: 213px !important; + padding-bottom: 10px !important; +} + +#aspect_discovery_SiteRecentSubmissions_p_recent-submission-view-more { +clear: both !important; +} + +#aspect_discovery_SimpleSearch_list_primary-search > ol > +li:nth-child(2) > div > div { + width: 8% !important; + float: left !important; + margin-left: 10px; + margin-top: 5px; +} + +#aspect_discovery_SimpleSearch_div_search-controls-gear { +margin-left: 90px !important; +} + +div.artifact-preview { + float: left; + margin-left: -60px; +} + +ul.ds-artifact-list li { + list-style: none; + clear: both; +} diff --git a/participatorio-utils/admin_scripts-crontab/create-permission_dspace_logs.sh b/participatorio-utils/admin_scripts-crontab/create-permission_dspace_logs.sh new file mode 100644 index 0000000000000000000000000000000000000000..ef8a90d2f6115462cac41fa5b2c921bc0dc97a0f --- /dev/null +++ b/participatorio-utils/admin_scripts-crontab/create-permission_dspace_logs.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +DSPACE_HOME="/home/dspace/webapp" +NEXT_DAY_DATE=$( date --date="tomorrow" +%Y-%m-%d ) + +OWNER="dspace:tomcat7" + +COCOON_LOG="${DSPACE_HOME}/log/cocoon.log.${NEXT_DAY_DATE}" +SOLR_LOG="${DSPACE_HOME}/log/solr.log.${NEXT_DAY_DATE}" +CHECKER_LOG="${DSPACE_HOME}/log/checker.log.${NEXT_DAY_DATE}" +DSPACE_LOG="${DSPACE_HOME}/log/dspace.log.${NEXT_DAY_DATE}" + +touch ${COCOON_LOG} && chown ${OWNER} ${COCOON_LOG} && chmod g+w ${COCOON_LOG} +touch ${SOLR_LOG} && chown ${OWNER} ${SOLR_LOG} && chmod g+w ${SOLR_LOG} +touch ${CHECKER_LOG} && chown ${OWNER} ${CHECKER_LOG} && chmod g+w ${CHECKER_LOG} +touch ${DSPACE_LOG} && chown ${OWNER} ${DSPACE_LOG} && chmod g+w ${DSPACE_LOG} + +exit 0 diff --git a/participatorio-utils/admin_scripts-crontab/dspace_crontab.txt b/participatorio-utils/admin_scripts-crontab/dspace_crontab.txt new file mode 100644 index 0000000000000000000000000000000000000000..afa06f3fbb68b35d5ae6991c7232ec4d7be1f593 --- /dev/null +++ b/participatorio-utils/admin_scripts-crontab/dspace_crontab.txt @@ -0,0 +1,109 @@ +#-------------------------------------------------------------------------------------------------------------- +# BASED ON: +# https://wiki.duraspace.org/display/DSDOC4x/Scheduled+Tasks+via+Cron +# +# HOW TO USE: +# To add it to crontab, execute "$ crontab e" as dspace user and add the following content to the end of file +#-------------------------------------------------------------------------------------------------------------- + +#----------------- +# GLOBAL VARIABLES +#----------------- +# Full path of your local DSpace Installation (e.g. /home/dspace or /dspace or similar) +DSPACE = /home/dspace/webapp + +# Shell to use +SHELL=/bin/sh + +# Add all major 'bin' directories to path +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + +# Set JAVA_OPTS with defaults for DSpace Cron Jobs. +# Only provides 512MB of memory by default (which should be enough for most sites). +JAVA_OPTS="-Xmx512M -Xms512M -Dfile.encoding=UTF-8" + +#-------------- +# HOURLY TASKS (Recommended to be run multiple times per day, if possible) +# At a minimum these tasks should be run daily. +#-------------- + +# Regenerate DSpace Sitemaps every 8 hours (12AM, 8AM, 4PM). +# SiteMaps ensure that your content is more findable in Google, Google Scholar, and other major search engines. +0 0,8,16 * * * $DSPACE/bin/dspace generate-sitemaps > /dev/null + +#---------------- +# DAILY TASKS +# (Recommended to be run once per day. Feel free to tweak the scheduled times below.) +#---------------- + +# Update the OAI-PMH index with the newest content (and re-optimize that index) at midnight every day +# NOTE: ONLY NECESSARY IF YOU ARE RUNNING OAI-PMH +# (This ensures new content is available via OAI-PMH and ensures the OAI-PMH index is optimized for better performance) +#0 0 * * * $DSPACE/bin/dspace oai import -o > /dev/null + +# Clean and Update the Discovery indexes at midnight every day +# (This ensures that any deleted documents are cleaned from the Discovery search/browse index) +0 0 * * * $DSPACE/bin/dspace index-discovery > /dev/null + +# Re-Optimize the Discovery indexes at 12:30 every day +# (This ensures that the Discovery Solr Index is re-optimized for better performance) +30 0 * * * $DSPACE/bin/dspace index-discovery -o > /dev/null + +# Cleanup Web Spiders from DSpace Statistics Solr Index at 01:00 every day +# NOTE: ONLY NECESSARY IF YOU ARE RUNNING SOLR STATISTICS +# (This removes any known web spiders from your usage statistics) +0 1 * * * $DSPACE/bin/dspace stats-util -i + +# Re-Optimize DSpace Statistics Solr Index at 01:30 every day +# NOTE: ONLY NECESSARY IF YOU ARE RUNNING SOLR STATISTICS +# (This ensures that the Statistics Solr Index is re-optimized for better performance) +30 1 * * * $DSPACE/bin/dspace stats-util -o + +# Send out subscription e-mails at 02:00 every day +# (This sends an email to any users who have "subscribed" to a Collection, notifying them of newly added content.) +0 2 * * * $DSPACE/bin/dspace sub-daily + +# Run the media filter at 03:00 every day. +# (This task ensures that thumbnails are generated for newly add images, +# and also ensures full text search is available for newly added PDF/Word/PPT/HTML documents) +0 3 * * * $DSPACE/bin/dspace filter-media + +# Run any Curation Tasks queued from the Admin UI at 04:00 every day +# (Ensures that any curation task that an administrator "queued" from the Admin UI is executed +# asynchronously behind the scenes) +0 4 * * * $DSPACE/bin/dspace curate -q admin_ui + +#---------------- +# WEEKLY TASKS +# (Recommended to be run once per week, but can be run more or less frequently, based on your local needs/policies) +#---------------- +# Run the checksum checker at 04:00 every Sunday +# By default it runs through every file (-l) and also prunes old results (-p) +# (This re-verifies the checksums of all files stored in DSpace. If any files have been changed/corrupted, checksums will differ.) +0 4 * * * $DSPACE/bin/dspace checker -l -p +# NOTE: LARGER SITES MAY WISH TO USE DIFFERENT OPTIONS. The above "-l" option tells DSpace to check *everything*. +# If your site is very large, you may need to only check a portion of your content per week. The below commented-out task +# would instead check all the content it can within *one hour*. The next week it would start again where it left off. +#0 4 * * 0 $DSPACE/bin/dspace checker -d 1h -p + +# Mail the results of the checksum checker (see above) to the configured "mail.admin" at 05:00 every Sunday. +# (This ensures the system administrator is notified whether any checksums were found to be different.) +0 5 * * 0 $DSPACE/bin/dspace checker-emailer + +#---------------- +# MONTHLY TASKS +# (Recommended to be run once per month, but can be run more or less frequently, based on your local needs/policies) +#---------------- +# Permanently delete any bitstreams flagged as "deleted" in DSpace, on the first of every month at 01:00 +# (This ensures that any files which were deleted from DSpace are actually removed from your local filesystem. +# By default they are just marked as deleted, but are not removed from the filesystem.) +0 1 1 * * $DSPACE/bin/dspace cleanup > /dev/null + +#---------------- +# YEARLY TASKS (Recommended to be run once per year) +#---------------- +# At 2:00AM every January 1, "shard" the DSpace Statistics Solr index. +# This ensures each year has its own Solr index, which improves performance. +# NOTE: ONLY NECESSARY IF YOU ARE RUNNING SOLR STATISTICS +# NOTE: This is scheduled here for 2:00AM so that it happens *after* the daily cleaning & re-optimization of this index. +0 2 1 1 * $DSPACE/bin/dspace stats-util -s diff --git a/participatorio-utils/admin_scripts-crontab/root_crontab.txt b/participatorio-utils/admin_scripts-crontab/root_crontab.txt new file mode 100644 index 0000000000000000000000000000000000000000..74fed68f44c820feb48c276d4013b985f77d72b7 --- /dev/null +++ b/participatorio-utils/admin_scripts-crontab/root_crontab.txt @@ -0,0 +1,7 @@ +#-------------------------------------------------------------------------------------------------------------- +# HOW TO USE: +# To add it to crontab, execute "$ crontab e" as root user and add the following content to the end of file +#-------------------------------------------------------------------------------------------------------------- + +#Create and adjust permissions of dspace's logs to avoid permission problems +30 23 * * * /home/dspace/admin-scripts/create-permission_dspace_logs.sh