protected DSpaceObject resolveHandle(String handle) { DSpaceObject dso = null; try { dso = handleService.resolveToObject(this.context, handle); } catch (SQLException ex) { log.error(ex); System.err.println( "A problem with the database connection " + "occurred. Canceled pending actions."); System.err.println(ex.getMessage()); ex.printStackTrace(System.err); System.exit(1); } catch (IllegalStateException ex) { log.error(ex); System.err.println("Cannot recognize identifier '" + handle + "', skipping."); return null; } if (dso == null) { System.err.println("Cannot resolve identifier '" + handle + "', skipping."); log.debug("Couldn't resolve identifier '" + handle + "', dso was null."); return null; } if (dso.getType() != Constants.SITE && dso.getType() != Constants.COMMUNITY && dso.getType() != Constants.COLLECTION && dso.getType() != Constants.ITEM) { System.err.println( contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + " are currently not " + "supported as independent entities. Bundles and Bitstreams " + "should be processed as part of their item."); return null; } return dso; }
/** * Match the URIs this subclass understands and return the corresponding resource. Since the * "dso_" format can lead to several different resource types, handle it here. * * @param context the context * @param request the request * @param response the response * @param pathElt the path elt * @return the DAV resource * @throws DAVStatusException the DAV status exception * @throws SQLException the SQL exception * @throws AuthorizeException the authorize exception */ protected static DAVResource matchResourceURI( Context context, HttpServletRequest request, HttpServletResponse response, String pathElt[]) throws DAVStatusException, SQLException, AuthorizeException { // Match /dso_<handle>{...} .. look for last "dso_" element if (pathElt[0].startsWith("dso_")) { int i = 1; for (; i < pathElt.length && pathElt[i].startsWith("dso_"); ++i) { // empty } --i; String handle = decodeHandle(pathElt[i].substring(4)); // Replace substituted handle separator char with '/' to // get back a normal handle: (inverse of getPathElt() above) int sepIndex = handle.indexOf(handleSeparator); if (sepIndex >= 0) { char hc[] = handle.toCharArray(); hc[sepIndex] = '/'; handle = String.copyValueOf(hc); } DSpaceObject dso = HandleManager.resolveToObject(context, handle); if (dso == null) { throw new DAVStatusException( HttpServletResponse.SC_NOT_FOUND, "Cannot resolve handle \"" + handle + "\""); } else if (dso.getType() == Constants.ITEM) { if (i + 1 < pathElt.length) { if (pathElt[i + 1].startsWith("bitstream_")) { Bitstream bs = DAVBitstream.findBitstream(context, (Item) dso, pathElt[i + 1]); if (bs == null) { throw new DAVStatusException( HttpServletResponse.SC_NOT_FOUND, "Bitstream \"" + pathElt[i + 1] + "\" not found in item: " + pathElt[i]); } return new DAVBitstream(context, request, response, pathElt, (Item) dso, bs); } else { throw new DAVStatusException( HttpServletResponse.SC_NOT_FOUND, "Illegal resource path, \"" + pathElt[i + 1] + "\" is not a Bitstream identifier for item: " + pathElt[i]); } } else { return new DAVItem(context, request, response, pathElt, (Item) dso); } } else if (dso.getType() == Constants.COLLECTION) { return new DAVCollection(context, request, response, pathElt, (Collection) dso); } else if (dso.getType() == Constants.COMMUNITY) { return new DAVCommunity(context, request, response, pathElt, (Community) dso); } else { throw new DAVStatusException( HttpServletResponse.SC_BAD_REQUEST, "Unrecognized DSpace object type for handle=" + handle); } } return null; }
/** * Delete the data about the DSpaceObject from the triplestore. All data about descendent * Subcommunities, Collections and Items will be deleted as well. */ public void delete(DSpaceObject dso, boolean reset) throws SQLException { if (dso.getType() != Constants.SITE && dso.getType() != Constants.COMMUNITY && dso.getType() != Constants.COLLECTION && dso.getType() != Constants.ITEM) { throw new IllegalArgumentException( contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + " is currently not supported as independent entity."); } if (dso.getType() == Constants.SITE) { // we don't need to iterate over all objects, use a shorctut: this.deleteAll(); } Callback callback = new Callback() { @Override protected void callback(DSpaceObject dso) throws SQLException { String identifier = RDFUtil.generateIdentifier(context, dso); if (StringUtils.isEmpty(identifier)) { System.err.println( "Cannot determine RDF URI for " + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + " " + dso.getID() + "(handle " + dso.getHandle() + ")" + ", skipping. Please " + "delete it specifing the RDF URI."); log.error( "Cannot detgermine RDF URI for " + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + " " + dso.getID() + "(handle " + dso.getHandle() + ")" + ", skipping deletion."); return; } report("Deleting Named Graph" + identifier); if (!dryrun) { storage.delete(identifier); } } }; this.dspaceDFS(dso, callback, false, reset); }
/** * Return a List of the policies for an object * * @param c current context * @param o object to retrieve policies for * @return List of <code>ResourcePolicy</code> objects */ public static List<ResourcePolicy> getPolicies(Context c, DSpaceObject o) throws SQLException { TableRowIterator tri = DatabaseManager.queryTable( c, "resourcepolicy", "SELECT * FROM resourcepolicy WHERE resource_type_id= ? AND resource_id= ? ", o.getType(), o.getID()); List<ResourcePolicy> policies = new ArrayList<ResourcePolicy>(); try { while (tri.hasNext()) { TableRow row = tri.next(); // first check the cache (FIXME: is this right?) ResourcePolicy cachepolicy = (ResourcePolicy) c.fromCache(ResourcePolicy.class, row.getIntColumn("policy_id")); if (cachepolicy != null) { policies.add(cachepolicy); } else { policies.add(new ResourcePolicy(c, row)); } } } finally { if (tri != null) { tri.close(); } } return policies; }
/** * Create URI as string for a given handle and optional bitstream. URI is relative to top of DAV * hierarchy, but starts with '/'. * * @param dso a DSpace object (Item, Collection, etc) * @param bsPid bitstream persistent identifier. * @return "absolute" URI from top of DAV hierarchy * @throws IOException Signals that an I/O exception has occurred. * @throws SQLException the SQL exception */ private String makeURI(DSpaceObject dso, String bsPid) throws IOException, SQLException { // make sure that bitstream actually exists: if (bsPid != null) { if (dso.getType() != Constants.ITEM) { log.warn("Non-Item with Bitstream Sequence ID in DAV Lookup."); return null; } try { int pid = Integer.parseInt(bsPid); if (DAVBitstream.getBitstreamBySequenceID((Item) dso, pid) == null) { log.warn("Bitstream Sequence ID Not Found in DAV Lookup: \"" + bsPid + "\""); return null; } } catch (NumberFormatException nfe) { log.warn("Invalid Bitstream Sequence ID in DAV Lookup: \"" + bsPid + "\""); return null; } } String base = "/" + DAVDSpaceObject.getPathElt(dso); if (bsPid != null) { return base + "/bitstream_" + bsPid; } else { return base; } }
private List disseminateListInternal(DSpaceObject dso, boolean addSchema) throws CrosswalkException, IOException, SQLException, AuthorizeException { if (dso.getType() != Constants.ITEM) throw new CrosswalkObjectNotSupported( "MODSDisseminationCrosswalk can only crosswalk an Item."); Item item = (Item) dso; initMap(); MetadataValue[] dc = item.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY); List result = new ArrayList(dc.length); for (int i = 0; i < dc.length; i++) { // Compose qualified DC name - schema.element[.qualifier] // e.g. "dc.title", "dc.subject.lcc", "lom.Classification.Keyword" String qdc = dc[i].getMetadataField().getSchema() + "." + ((dc[i].getMetadataField().getQualifier() == null) ? dc[i].getMetadataField().getElement() : (dc[i].getMetadataField().getElement() + "." + dc[i].getMetadataField().getQualifier())); modsTriple trip = (modsTriple) modsMap.get(qdc); if (trip == null) log.warn("WARNING: " + getPluginInstanceName() + ": No MODS mapping for \"" + qdc + "\""); else { try { Element me = (Element) trip.xml.clone(); if (addSchema) me.setAttribute("schemaLocation", schemaLocation, XSI_NS); Iterator ni = trip.xpath.selectNodes(me).iterator(); if (!ni.hasNext()) log.warn( "XPath \"" + trip.xpath.getXPath() + "\" found no elements in \"" + outputUgly.outputString(me) + "\", qdc=" + qdc); while (ni.hasNext()) { Object what = ni.next(); if (what instanceof Element) ((Element) what).setText(dc[i].getValue()); else if (what instanceof Attribute) ((Attribute) what).setValue(dc[i].getValue()); else if (what instanceof Text) ((Text) what).setText(dc[i].getValue()); else log.warn("Got unknown object from XPath, class=" + what.getClass().getName()); } result.add(me); } catch (JDOMException je) { log.error( "Error following XPath in modsTriple: context=" + outputUgly.outputString(trip.xml) + ", xpath=" + trip.xpath.getXPath() + ", exception=" + je.toString()); } } } return result; }
/** * removes ALL policies for an object. FIXME doesn't check authorization * * @param c DSpace context * @param o object to remove policies for * @throws SQLException if there's a database problem */ public static void removeAllPolicies(Context c, DSpaceObject o) throws SQLException { // FIXME: authorization check? DatabaseManager.updateQuery( c, "DELETE FROM resourcepolicy WHERE " + "resource_type_id= ? AND resource_id= ? ", o.getType(), o.getID()); }
private static String formatAction(Action action, DSpaceObject object) { try { String objText = Constants.typeText[object.getType()].toLowerCase(); return action.text() + "_" + objText; } catch (Exception e) { } return ""; }
/** * Removes all policies from a group for a particular object that belong to a Group. FIXME doesn't * check authorization * * @param c current context * @param o the object * @param g the group * @throws SQLException if there's a database problem */ public static void removeGroupPolicies(Context c, DSpaceObject o, Group g) throws SQLException { DatabaseManager.updateQuery( c, "DELETE FROM resourcepolicy WHERE " + "resource_type_id= ? AND resource_id= ? AND epersongroup_id= ? ", o.getType(), o.getID(), g.getID()); }
/** * Returns all groups authorized to perform an action on an object. Returns empty array if no * matches. * * @param c current context * @param o object * @param actionID ID of action frm <code>org.dspace.core.Constants</code> * @return array of <code>Group</code>s that can perform the specified action on the specified * object * @throws java.sql.SQLException if there's a database problem */ public static Group[] getAuthorizedGroups(Context c, DSpaceObject o, int actionID) throws java.sql.SQLException { // do query matching groups, actions, and objects TableRowIterator tri = DatabaseManager.queryTable( c, "resourcepolicy", "SELECT * FROM resourcepolicy WHERE resource_type_id= ? " + "AND resource_id= ? AND action_id= ? ", o.getType(), o.getID(), actionID); List<Group> groups = new ArrayList<Group>(); try { while (tri.hasNext()) { TableRow row = tri.next(); // first check the cache (FIXME: is this right?) ResourcePolicy cachepolicy = (ResourcePolicy) c.fromCache(ResourcePolicy.class, row.getIntColumn("policy_id")); ResourcePolicy myPolicy = null; if (cachepolicy != null) { myPolicy = cachepolicy; } else { myPolicy = new ResourcePolicy(c, row); } // now do we have a group? Group myGroup = myPolicy.getGroup(); if (myGroup != null) { groups.add(myGroup); } } } finally { if (tri != null) { tri.close(); } } Group[] groupArray = new Group[groups.size()]; groupArray = groups.toArray(groupArray); return groupArray; }
/** * Remove all policies from an object that match a given action. FIXME doesn't check authorization * * @param context current context * @param dso object to remove policies from * @param actionID ID of action to match from <code>org.dspace.core.Constants</code>, or -1=all * @throws SQLException if there's a database problem */ public static void removePoliciesActionFilter(Context context, DSpaceObject dso, int actionID) throws SQLException { if (actionID == -1) { // remove all policies from object removeAllPolicies(context, dso); } else { DatabaseManager.updateQuery( context, "DELETE FROM resourcepolicy WHERE resource_type_id= ? AND " + "resource_id= ? AND action_id= ? ", dso.getType(), dso.getID(), actionID); } }
private static String formatMessage(DSpaceObject object) { try { String objText = Constants.typeText[object.getType()].toLowerCase(); String handle = object.getHandle(); /* Emulate Item logger */ if (handle != null && object instanceof Item) { return "handle=" + object.getHandle(); } else { return objText + "_id=" + object.getID(); } } catch (Exception e) { } return ""; }
public Element disseminateElement(DSpaceObject dso) throws CrosswalkException, IOException, SQLException, AuthorizeException { if (dso.getType() != Constants.ITEM) { throw new CrosswalkObjectNotSupported( "METSDisseminationCrosswalk can only crosswalk an Item."); } Item item = (Item) dso; PackageDisseminator dip = (PackageDisseminator) PluginManager.getNamedPlugin(PackageDisseminator.class, METS_PACKAGER_PLUGIN); if (dip == null) { throw new CrosswalkInternalException( "Cannot find a disseminate plugin for package=" + METS_PACKAGER_PLUGIN); } try { // Set the manifestOnly=true param so we just get METS document PackageParameters pparams = new PackageParameters(); pparams.put("manifestOnly", "true"); // Create a temporary file to disseminate into String tempDirectory = ConfigurationManager.getProperty("upload.temp.dir"); File tempFile = File.createTempFile("METSDissemination" + item.hashCode(), null, new File(tempDirectory)); tempFile.deleteOnExit(); // Disseminate METS to temp file Context context = new Context(); dip.disseminate(context, item, pparams, tempFile); try { SAXBuilder builder = new SAXBuilder(); Document metsDocument = builder.build(tempFile); return metsDocument.getRootElement(); } catch (JDOMException je) { throw new MetadataValidationException( "Error parsing METS (see wrapped error message for more details) ", je); } } catch (PackageException pe) { throw new CrosswalkInternalException( "Failed making METS manifest in packager (see wrapped error message for more details) ", pe); } }
/** * Process sets of objects to add, update, and delete in index. Correct for interactions between * the sets -- e.g. objects which were deleted do not need to be added or updated, new objects * don't also need an update, etc. */ public void end(Context ctx) throws Exception { if (objectsToUpdate != null && handlesToDelete != null) { // update the changed Items not deleted because they were on create list for (DSpaceObject iu : objectsToUpdate) { /* we let all types through here and * allow the search DSIndexer to make * decisions on indexing and/or removal */ String hdl = iu.getHandle(); if (hdl != null && !handlesToDelete.contains(hdl)) { try { DSIndexer.indexContent(ctx, iu, true); log.debug( "Indexed " + Constants.typeText[iu.getType()] + ", id=" + String.valueOf(iu.getID()) + ", handle=" + hdl); } catch (Exception e) { log.error("Failed while indexing object: ", e); } } } for (String hdl : handlesToDelete) { try { DSIndexer.unIndexContent(ctx, hdl); if (log.isDebugEnabled()) { log.debug("UN-Indexed Item, handle=" + hdl); } } catch (Exception e) { log.error("Failed while UN-indexing object: " + hdl, e); } } } // "free" the resources objectsToUpdate = null; handlesToDelete = null; }
/** * Ingest a whole document. Build Document object around root element, and feed that to the * transformation, since it may get handled differently than a List of metadata elements. */ public void ingest(Context context, DSpaceObject dso, Element root) throws CrosswalkException, IOException, SQLException, AuthorizeException { if (dso.getType() != Constants.ITEM) throw new CrosswalkObjectNotSupported( "XsltSubmissionionCrosswalk can only crosswalk to an Item."); Item item = (Item) dso; XSLTransformer xform = getTransformer(DIRECTION); if (xform == null) throw new CrosswalkInternalException( "Failed to initialize transformer, probably error loading stylesheet."); try { Document dimDoc = xform.transform(new Document((Element) root.clone())); applyDim(dimDoc.getRootElement().getChildren(), item); } catch (XSLTransformException e) { log.error("Got error: " + e.toString()); throw new CrosswalkInternalException("XSL Transformation failed: " + e.toString()); } }
public List disseminateList(DSpaceObject dso) throws CrosswalkException, IOException, SQLException, AuthorizeException { init(); if (dso.getType() != Constants.ITEM) throw new CrosswalkObjectNotSupported( "XSLTDisseminationCrosswalk can only crosswalk an Item."); Item item = (Item) dso; XSLTransformer xform = getTransformer(DIRECTION); if (xform == null) throw new CrosswalkInternalException( "Failed to initialize transformer, probably error loading stylesheet."); try { return xform.transform(getDim(item).getChildren()); } catch (XSLTransformException e) { log.error("Got error: " + e.toString()); throw new CrosswalkInternalException("XSL translation failed: " + e.toString()); } }
/** * VERY crude dissemination: just look for the first bitstream with the PDF package type, and toss * it out. Works on packages importer with this packager, and maybe some others. */ public void disseminate( Context context, DSpaceObject dso, PackageParameters params, OutputStream out) throws PackageValidationException, CrosswalkException, AuthorizeException, SQLException, IOException { if (dso.getType() != Constants.ITEM) throw new PackageValidationException( "This disseminator can only handle objects of type ITEM."); Item item = (Item) dso; try { BitstreamFormat pdff = BitstreamFormat.findByShortDescription(context, BITSTREAM_FORMAT_NAME); if (pdff == null) throw new PackageValidationException( "Cannot find BitstreamFormat \"" + BITSTREAM_FORMAT_NAME + "\""); Bitstream pkgBs = PackageUtils.getBitstreamByFormat(item, pdff, Constants.DEFAULT_BUNDLE_NAME); if (pkgBs == null) throw new PackageValidationException( "Cannot find Bitstream with format \"" + BITSTREAM_FORMAT_NAME + "\""); Utils.copy(pkgBs.retrieve(), out); } finally { } }
/** * Perform the curation task upon passed DSO * * @param dso the DSpace object * @throws IOException */ @Override public int perform(DSpaceObject dso) throws IOException { if (dso.getType() == Constants.ITEM) { Item item = (Item) dso; int count = 0; try { StringBuilder sb = new StringBuilder(); String handle = item.getHandle(); if (handle == null) { // we are still in workflow - no handle assigned handle = "in workflow"; } sb.append("Item: ").append(handle); for (String req : getReqList(item.getOwningCollection().getHandle())) { DCValue[] vals = item.getMetadata(req); if (vals.length == 0) { sb.append(" missing required field: ").append(req); count++; } } if (count == 0) { sb.append(" has all required fields"); } report(sb.toString()); setResult(sb.toString()); } catch (DCInputsReaderException dcrE) { throw new IOException(dcrE.getMessage(), dcrE); } catch (SQLException sqlE) { throw new IOException(sqlE.getMessage(), sqlE); } return (count == 0) ? Curator.CURATE_SUCCESS : Curator.CURATE_FAIL; } else { setResult("Object skipped"); return Curator.CURATE_SKIP; } }
public boolean canDisseminate(DSpaceObject dso) { return dso.getType() == Constants.ITEM; }
/** * Export the object (Item, Collection, or Community) to a package file on the indicated * OutputStream. Gets an exception of the object cannot be packaged or there is a failure creating * the package. * * @param context - DSpace context. * @param dso - DSpace object (item, collection, etc) * @param pkg - output stream on which to write package * @throws PackageException if package cannot be created or there is a fatal error in creating it. */ public void disseminate( Context context, DSpaceObject dso, PackageParameters params, OutputStream pkg) throws PackageValidationException, CrosswalkException, AuthorizeException, SQLException, IOException { if (dso.getType() == Constants.ITEM) { Item item = (Item) dso; long lmTime = item.getLastModified().getTime(); // how to handle unauthorized bundle/bitstream: String unauth = (params == null) ? null : params.getProperty("unauthorized"); if (params != null && params.getProperty("manifestOnly") != null) { extraFiles = null; writeManifest(context, item, params, pkg); } else { extraFiles = new HashMap(); ZipOutputStream zip = new ZipOutputStream(pkg); zip.setComment("METS archive created by DSpace METSDisseminationCrosswalk"); // write manifest first. ZipEntry me = new ZipEntry(MANIFEST_FILE); me.setTime(lmTime); zip.putNextEntry(me); writeManifest(context, item, params, zip); zip.closeEntry(); // copy extra (meta?) bitstreams into zip Iterator fi = extraFiles.keySet().iterator(); while (fi.hasNext()) { String fname = (String) fi.next(); ZipEntry ze = new ZipEntry(fname); ze.setTime(lmTime); zip.putNextEntry(ze); Utils.copy((InputStream) extraFiles.get(fname), zip); zip.closeEntry(); } // copy all non-meta bitstreams into zip Bundle bundles[] = item.getBundles(); for (int i = 0; i < bundles.length; i++) { if (!PackageUtils.isMetaInfoBundle(bundles[i])) { // unauthorized bundle? if (!AuthorizeManager.authorizeActionBoolean(context, bundles[i], Constants.READ)) { if (unauth != null && (unauth.equalsIgnoreCase("skip"))) { log.warn( "Skipping Bundle[\"" + bundles[i].getName() + "\"] because you are not authorized to read it."); continue; } else throw new AuthorizeException( "Not authorized to read Bundle named \"" + bundles[i].getName() + "\""); } Bitstream[] bitstreams = bundles[i].getBitstreams(); for (int k = 0; k < bitstreams.length; k++) { boolean auth = AuthorizeManager.authorizeActionBoolean(context, bitstreams[k], Constants.READ); if (auth || (unauth != null && unauth.equalsIgnoreCase("zero"))) { ZipEntry ze = new ZipEntry(makeBitstreamName(bitstreams[k])); ze.setTime(lmTime); ze.setSize(auth ? bitstreams[k].getSize() : 0); zip.putNextEntry(ze); if (auth) Utils.copy(bitstreams[k].retrieve(), zip); else log.warn( "Adding zero-length file for Bitstream, SID=" + String.valueOf(bitstreams[k].getSequenceID()) + ", not authorized for READ."); zip.closeEntry(); } else if (unauth != null && unauth.equalsIgnoreCase("skip")) { log.warn( "Skipping Bitstream, SID=" + String.valueOf(bitstreams[k].getSequenceID()) + ", not authorized for READ."); } else { throw new AuthorizeException( "Not authorized to read Bitstream, SID=" + String.valueOf(bitstreams[k].getSequenceID())); } } } } zip.close(); extraFiles = null; } } else throw new PackageValidationException("Can only disseminate an Item now."); }
@Override protected void doDSGet(Context context, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException, AuthorizeException { Item item = null; Bitstream bitstream = null; // Get the ID from the URL String idString = request.getPathInfo(); String handle = ""; String sequenceText = ""; String filename = null; int sequenceID; // Parse 'handle' and 'sequence' (bitstream seq. number) out // of remaining URL path, which is typically of the format: // {handle}/{sequence}/{bitstream-name} // But since the bitstream name MAY have any number of "/"s in // it, and the handle is guaranteed to have one slash, we // scan from the start to pick out handle and sequence: // Remove leading slash if any: if (idString.startsWith("/")) { idString = idString.substring(1); } // skip first slash within handle int slashIndex = idString.indexOf('/'); if (slashIndex != -1) { slashIndex = idString.indexOf('/', slashIndex + 1); if (slashIndex != -1) { handle = idString.substring(0, slashIndex); int slash2 = idString.indexOf('/', slashIndex + 1); if (slash2 != -1) { sequenceText = idString.substring(slashIndex + 1, slash2); filename = idString.substring(slash2 + 1); } } } try { sequenceID = Integer.parseInt(sequenceText); } catch (NumberFormatException nfe) { sequenceID = -1; } // Now try and retrieve the item DSpaceObject dso = HandleManager.resolveToObject(context, handle); // Make sure we have valid item and sequence number if (dso != null && dso.getType() == Constants.ITEM && sequenceID >= 0) { item = (Item) dso; if (item.isWithdrawn()) { log.info( LogManager.getHeader( context, "view_bitstream", "handle=" + handle + ",withdrawn=true")); JSPManager.showJSP(request, response, "/tombstone.jsp"); return; } boolean found = false; Bundle[] bundles = item.getBundles(); for (int i = 0; (i < bundles.length) && !found; i++) { Bitstream[] bitstreams = bundles[i].getBitstreams(); for (int k = 0; (k < bitstreams.length) && !found; k++) { if (sequenceID == bitstreams[k].getSequenceID()) { bitstream = bitstreams[k]; found = true; } } } } if (bitstream == null || filename == null || !filename.equals(bitstream.getName())) { // No bitstream found or filename was wrong -- ID invalid log.info(LogManager.getHeader(context, "invalid_id", "path=" + idString)); JSPManager.showInvalidIDError(request, response, idString, Constants.BITSTREAM); return; } log.info(LogManager.getHeader(context, "view_bitstream", "bitstream_id=" + bitstream.getID())); // Modification date // Only use last-modified if this is an anonymous access // - caching content that may be generated under authorisation // is a security problem if (context.getCurrentUser() == null) { // TODO: Currently the date of the item, since we don't have dates // for files response.setDateHeader("Last-Modified", item.getLastModified().getTime()); // Check for if-modified-since header long modSince = request.getDateHeader("If-Modified-Since"); if (modSince != -1 && item.getLastModified().getTime() < modSince) { // Item has not been modified since requested date, // hence bitstream has not; return 304 response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); return; } } // Pipe the bits InputStream is = bitstream.retrieve(); // Set the response MIME type response.setContentType(bitstream.getFormat().getMIMEType()); // Response length response.setHeader("Content-Length", String.valueOf(bitstream.getSize())); if (threshold != -1 && bitstream.getSize() >= threshold) { setBitstreamDisposition(bitstream.getName(), request, response); } Utils.bufferedCopy(is, response.getOutputStream()); is.close(); response.getOutputStream().flush(); }
@Override public List<Item> getItems( DSpaceObject scope, String startDate, String endDate, int offset, int limit, boolean items, boolean collections, boolean withdrawn) throws ParseException { try { // Put together our query. Note there is no need for an // "in_archive=true" condition, we are using the existence of a // persistent identifier as our 'existence criterion'. String query = "SELECT p.value, p.type_id, p.resource_id as item_id, " + "i.withdrawn, i.last_modified " + "FROM externalidentifier p, item i"; // We are building a complex query that may contain a variable // about of input data points. To accomidate this while still // providing type safty we build a list of parameters to be // plugged into the query at the database level. List parameters = new ArrayList(); if (scope != null) { if (scope.getType() == Constants.COLLECTION) { query += ", collection2item cl2i"; } else if (scope.getType() == Constants.COMMUNITY) { query += ", communities2item cm2i"; } } query += " WHERE p.resource_type_id=" + Constants.ITEM + " AND p.resource_id = i.item_id "; if (scope != null) { if (scope.getType() == Constants.COLLECTION) { query += " AND cl2i.collection_id= ? " + " AND cl2i.item_id = p.resource_id "; parameters.add(scope.getID()); } else if (scope.getType() == Constants.COMMUNITY) { query += " AND cm2i.community_id= ? " + " AND cm2i.item_id = p.resource_id"; parameters.add(scope.getID()); } } if (startDate != null) { query = query + " AND i.last_modified >= ? "; parameters.add(toTimestamp(startDate, false)); } if (endDate != null) { /* * If the end date has seconds precision, e.g.: * * 2004-04-29T13:45:43Z * * we need to add 999 milliseconds to this. This is because SQL * TIMESTAMPs have millisecond precision, and so might have a value: * * 2004-04-29T13:45:43.952Z * * and so <= '2004-04-29T13:45:43Z' would not pick this up. Reading * things out of the database, TIMESTAMPs are rounded down, so the * above value would be read as '2004-04-29T13:45:43Z', and * therefore a caller would expect <= '2004-04-29T13:45:43Z' to * include that value. * * Got that? ;-) */ boolean selfGenerated = false; if (endDate.length() == 20) { endDate = endDate.substring(0, 19) + ".999Z"; selfGenerated = true; } query += " AND i.last_modified <= ? "; parameters.add(toTimestamp(endDate, selfGenerated)); } if (!withdrawn) { // Exclude withdrawn items if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) { query += " AND withdrawn=0 "; } else { // postgres uses booleans query += " AND withdrawn=false "; } } // Order by item ID, so that for a given harvest the order will be // consistent. This is so that big harvests can be broken up into // several smaller operations (e.g. for OAI resumption tokens.) query += " ORDER BY p.resource_id"; // Execute Object[] parametersArray = parameters.toArray(); TableRowIterator tri = DatabaseManager.query(context, query, parametersArray); return returnAsList(tri); } catch (SQLException sqle) { throw new RuntimeException(sqle); } }
protected void convert(DSpaceObject dso, boolean reset) throws SQLException { if (dso.getType() != Constants.SITE && dso.getType() != Constants.COMMUNITY && dso.getType() != Constants.COLLECTION && dso.getType() != Constants.ITEM) { throw new IllegalArgumentException( contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + " is currently not supported as independent entity."); } Callback callback = new Callback() { @Override protected void callback(DSpaceObject dso) throws SQLException { Model converted = null; try { if (dryrun) { converted = RDFUtil.convert(context, dso); } else { converted = RDFUtil.convertAndStore(context, dso); } } catch (ItemNotArchivedException ex) { if (!(dso instanceof Item)) throw new IllegalStateException(ex.getMessage(), ex); report( "Skipping conversion of Item " + dso.getID() + " (handle " + dso.getHandle() + "): Item is not " + "archived."); return; } catch (ItemWithdrawnException ex) { if (!(dso instanceof Item)) throw new IllegalStateException(ex.getMessage(), ex); report( "Skipping conversion of Item " + dso.getID() + " (handle " + dso.getHandle() + "): Item is " + "withdrawn."); return; } catch (ItemNotDiscoverableException ex) { if (!(dso instanceof Item)) throw new IllegalStateException(ex.getMessage(), ex); report( "Skipping conversion of Item " + dso.getID() + " (handle " + dso.getHandle() + "): Item is not " + "discoverable."); return; } catch (AuthorizeException ex) { report( "Skipping conversion of " + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + " " + dso.getID() + " (handle " + dso.getHandle() + ")" + ", not authorized: " + ex.getMessage()); return; } catch (RDFMissingIdentifierException ex) { String errormessage = "Skipping conversion of " + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + " " + dso.getID() + " (handle " + dso.getHandle() + ")."; log.error(errormessage, ex); System.err.println(errormessage + " Error while converting: " + ex.getMessage()); return; } if (stdout) { if (converted == null) { System.err.println( "Conversion of " + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + " " + dso.getID() + " resulted in no data."); } else { converted.write(System.out, lang); } } if (converted != null) converted.close(); } }; this.dspaceDFS(dso, callback, true, reset); }
public static void main(String[] argv) throws Exception { Options options = new Options(); options.addOption("c", "collection", true, "destination collection(s) Handle (repeatable)"); options.addOption("e", "eperson", true, "email address of eperson doing importing"); options.addOption( "w", "install", false, "disable workflow; install immediately without going through collection's workflow"); options.addOption("t", "type", true, "package type or MIMEtype"); options.addOption( "o", "option", true, "Packager option to pass to plugin, \"name=value\" (repeatable)"); options.addOption( "d", "disseminate", false, "Disseminate package (output); default is to submit."); options.addOption("i", "item", true, "Handle of item to disseminate."); options.addOption("h", "help", false, "help"); CommandLineParser parser = new PosixParser(); CommandLine line = parser.parse(options, argv); String sourceFile = null; String eperson = null; String[] collections = null; boolean useWorkflow = true; String packageType = null; boolean submit = true; String itemHandle = null; PackageParameters pkgParams = new PackageParameters(); if (line.hasOption('h')) { HelpFormatter myhelp = new HelpFormatter(); myhelp.printHelp("Packager [options] package-file|-\n", options); System.out.println("\nAvailable Submission Package (SIP) types:"); String pn[] = PluginManager.getAllPluginNames(PackageIngester.class); for (int i = 0; i < pn.length; ++i) System.out.println(" " + pn[i]); System.out.println("\nAvailable Dissemination Package (DIP) types:"); pn = PluginManager.getAllPluginNames(PackageDisseminator.class); for (int i = 0; i < pn.length; ++i) System.out.println(" " + pn[i]); System.exit(0); } if (line.hasOption('w')) useWorkflow = false; if (line.hasOption('e')) eperson = line.getOptionValue('e'); if (line.hasOption('c')) collections = line.getOptionValues('c'); if (line.hasOption('t')) packageType = line.getOptionValue('t'); if (line.hasOption('i')) itemHandle = line.getOptionValue('i'); String files[] = line.getArgs(); if (files.length > 0) sourceFile = files[0]; if (line.hasOption('d')) submit = false; if (line.hasOption('o')) { String popt[] = line.getOptionValues('o'); for (int i = 0; i < popt.length; ++i) { String pair[] = popt[i].split("\\=", 2); if (pair.length == 2) pkgParams.addProperty(pair[0].trim(), pair[1].trim()); else if (pair.length == 1) pkgParams.addProperty(pair[0].trim(), ""); else System.err.println("Warning: Illegal package option format: \"" + popt[i] + "\""); } } // Sanity checks on arg list: required args if (sourceFile == null || eperson == null || packageType == null || (submit && collections == null)) { System.err.println("Error - missing a REQUIRED argument or option.\n"); HelpFormatter myhelp = new HelpFormatter(); myhelp.printHelp("PackageManager [options] package-file|-\n", options); System.exit(0); } // find the EPerson, assign to context Context context = new Context(); EPerson myEPerson = null; myEPerson = EPerson.findByEmail(context, eperson); if (myEPerson == null) usageError("Error, eperson cannot be found: " + eperson); context.setCurrentUser(myEPerson); if (submit) { // make sure we have an input file // GWaller 11/1/10 Disable piping of input in - we need to archive the package so it is // simpler to assume a file stream // rather than save the System.in bytes and re-read. if (sourceFile.equals("-")) { usageError( "Error, input piping not allowed. Specify a file name of a physical file to read"); } InputStream source = new FileInputStream(sourceFile); PackageIngester sip = (PackageIngester) PluginManager.getNamedPlugin(PackageIngester.class, packageType); if (sip == null) usageError("Error, Unknown package type: " + packageType); // find collections Collection[] mycollections = null; System.out.println("Destination collections:"); // validate each collection arg to see if it's a real collection mycollections = new Collection[collections.length]; for (int i = 0; i < collections.length; i++) { // sanity check: did handle resolve, and to a collection? DSpaceObject dso = HandleManager.resolveToObject(context, collections[i]); if (dso == null) throw new IllegalArgumentException( "Bad collection list -- " + "Cannot resolve collection handle \"" + collections[i] + "\""); else if (dso.getType() != Constants.COLLECTION) throw new IllegalArgumentException( "Bad collection list -- " + "Object at handle \"" + collections[i] + "\" is not a collection!"); mycollections[i] = (Collection) dso; System.out.println( (i == 0 ? " Owning " : " ") + " Collection: " + mycollections[i].getMetadata("name")); } try { // GWaller 26/08/09 Support array of collections WorkspaceItem wi = sip.ingest(context, mycollections, source, pkgParams, null); // GWaller 11/1/10 IssueID #157 Archive the package InputStream sourceCopy = new FileInputStream(sourceFile); Bundle archivedBundle = BundleUtils.getBundleByName(wi.getItem(), Constants.ARCHIVED_CONTENT_PACKAGE_BUNDLE); Bitstream bs = archivedBundle.createBitstream(sourceCopy); bs.setName(new File(sourceFile).getName()); bs.update(); archivedBundle.update(); if (useWorkflow) { String handle = null; // Check if workflow completes immediately, and // return Handle if so. WorkflowItem wfi = WorkflowManager.startWithoutNotify(context, wi); if (wfi.getState() == WorkflowManager.WFSTATE_ARCHIVE) { Item ni = wfi.getItem(); handle = HandleManager.findHandle(context, ni); } if (handle == null) System.out.println("Created Workflow item, ID=" + String.valueOf(wfi.getID())); else System.out.println("Created and installed item, handle=" + handle); } else { InstallItem.installItem(context, wi); System.out.println( "Created and installed item, handle=" + HandleManager.findHandle(context, wi.getItem())); } context.complete(); System.exit(0); } catch (Exception e) { // abort all operations context.abort(); e.printStackTrace(); System.out.println(e); System.exit(1); } } else { OutputStream dest = (sourceFile.equals("-")) ? (OutputStream) System.out : (OutputStream) (new FileOutputStream(sourceFile)); PackageDisseminator dip = (PackageDisseminator) PluginManager.getNamedPlugin(PackageDisseminator.class, packageType); if (dip == null) usageError("Error, Unknown package type: " + packageType); DSpaceObject dso = HandleManager.resolveToObject(context, itemHandle); if (dso == null) throw new IllegalArgumentException( "Bad Item handle -- " + "Cannot resolve handle \"" + itemHandle); dip.disseminate(context, dso, pkgParams, dest); } }
protected void dspaceDFS(DSpaceObject dso, Callback callback, boolean check, boolean reset) throws SQLException { if (dso.getType() != Constants.SITE && dso.getType() != Constants.COMMUNITY && dso.getType() != Constants.COLLECTION && dso.getType() != Constants.ITEM) { throw new IllegalArgumentException( contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + " is currently not supported as independent entity."); } if (reset) { this.processed.clear(); } if (isProcessed(dso)) { log.debug( "Skipping processing of " + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + " " + dso.getID() + " (handle " + dso.getHandle() + "), already processed."); return; } markProcessed(dso); // this is useful to debug depth first search, but it is really noisy. // log.debug("Procesing " + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + // " " + dso.getID() + ":" + dso.getHandle() + "."); // if this method is used for conversion we should check if we have the // permissions to read a DSO before converting all of it decendents // (e.g. check read permission on a community before converting all of // its subcommunties and collections). // just skip items with missing permissions and report them. if (check) { try { RDFUtil.isPublic(context, dso); } catch (ItemNotArchivedException ex) { if (!(dso instanceof Item)) throw new IllegalStateException(ex.getMessage(), ex); report( "Skipping processing of Item " + dso.getID() + " (handle " + dso.getHandle() + "): Item is not " + "archived."); return; } catch (ItemWithdrawnException ex) { if (!(dso instanceof Item)) throw new IllegalStateException(ex.getMessage(), ex); report( "Skipping processing of Item " + dso.getID() + " (handle " + dso.getHandle() + "): Item is " + "withdrawn."); return; } catch (ItemNotDiscoverableException ex) { if (!(dso instanceof Item)) throw new IllegalStateException(ex.getMessage(), ex); report( "Skipping processing of Item " + dso.getID() + " (handle " + dso.getHandle() + "): Item is not " + "discoverable."); return; } catch (AuthorizeException ex) { report( "Skipping processing of " + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + " " + dso.getID() + " (handle " + dso.getHandle() + ")" + ", not authorized: " + ex.getMessage()); return; } } if (dso instanceof Site) { List<Community> communities = communityService.findAllTop(context); for (Community community : communities) { this.dspaceDFS(community, callback, check, false); } } if (dso instanceof Community) { List<Community> subcommunities = ((Community) dso).getSubcommunities(); for (Community sub : subcommunities) { this.dspaceDFS(sub, callback, check, false); } List<Collection> collections = ((Community) dso).getCollections(); for (Collection collection : collections) { this.dspaceDFS(collection, callback, check, false); } } if (dso instanceof Collection) { Iterator<Item> items = itemService.findAllByCollection(context, (Collection) dso); while (items.hasNext()) { Item item = items.next(); this.dspaceDFS(item, callback, check, false); } } // Currently Bundles and Bitsreams aren't supported as independent entities. // They should be converted as part of an item. So we do not need to make // the recursive call for them. An item itself will be converted as part // of the callback call below. // The following code is left here for the day, we decide to also convert // bundles and/or bitstreams. // // if (dso instanceof Item) // { // Bundle[] bundles = ((Item) dso).getBundles(); // for (Bundle bundle : bundles) // { // this.dspaceDFS(bundle, callback, check, false); // } // } // // if (dso instanceof Bundle) // { // Bitstream[] bistreams = ((Bundle) dso).getBitstreams(); // for (Bitstream bitstream : bistreams) // { // this.dspaceDFS(bitstream, callback, check, false); // } // } callback.callback(dso); report( "Processed " + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) + " " + dso.getID() + " (handle " + dso.getHandle() + ")."); }
protected void doDSGet(Context context, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException, AuthorizeException { includeAll = ConfigurationManager.getBooleanProperty("harvest.includerestricted.rss", true); String path = request.getPathInfo(); String feedType = null; String handle = null; // build label map from localized Messages resource bundle Locale locale = request.getLocale(); ResourceBundle msgs = ResourceBundle.getBundle("Messages", locale); Map<String, String> labelMap = new HashMap<String, String>(); labelMap.put(SyndicationFeed.MSG_UNTITLED, msgs.getString(clazz + ".notitle")); labelMap.put(SyndicationFeed.MSG_LOGO_TITLE, msgs.getString(clazz + ".logo.title")); labelMap.put( SyndicationFeed.MSG_FEED_DESCRIPTION, msgs.getString(clazz + ".general-feed.description")); labelMap.put(SyndicationFeed.MSG_UITYPE, SyndicationFeed.UITYPE_JSPUI); for (String selector : SyndicationFeed.getDescriptionSelectors()) { labelMap.put("metadata." + selector, msgs.getString(SyndicationFeed.MSG_METADATA + selector)); } if (path != null) { // substring(1) is to remove initial '/' path = path.substring(1); int split = path.indexOf('/'); if (split != -1) { feedType = path.substring(0, split); handle = path.substring(split + 1); } } DSpaceObject dso = null; // as long as this is not a site wide feed, // attempt to retrieve the Collection or Community object if (handle != null && !handle.equals(SITE_FEED_KEY)) { // Determine if handle is a valid reference dso = HandleManager.resolveToObject(context, handle); if (dso == null) { log.info(LogManager.getHeader(context, "invalid_handle", "path=" + path)); JSPManager.showInvalidIDError(request, response, handle, -1); return; } } if (!enabled || (dso != null && (dso.getType() != Constants.COLLECTION && dso.getType() != Constants.COMMUNITY))) { log.info(LogManager.getHeader(context, "invalid_id", "path=" + path)); JSPManager.showInvalidIDError(request, response, path, -1); return; } // Determine if requested format is supported if (feedType == null || !formats.contains(feedType)) { log.info(LogManager.getHeader(context, "invalid_syndformat", "path=" + path)); JSPManager.showInvalidIDError(request, response, path, -1); return; } if (dso != null && dso.getType() == Constants.COLLECTION) { labelMap.put( SyndicationFeed.MSG_FEED_TITLE, MessageFormat.format( msgs.getString(clazz + ".feed.title"), msgs.getString(clazz + ".feed-type.collection"), dso.getMetadata("short_description"))); } else if (dso != null && dso.getType() == Constants.COMMUNITY) { labelMap.put( SyndicationFeed.MSG_FEED_TITLE, MessageFormat.format( msgs.getString(clazz + ".feed.title"), msgs.getString(clazz + ".feed-type.community"), dso.getMetadata("short_description"))); } // Lookup or generate the feed // Cache key is handle + locale String cacheKey = (handle == null ? "site" : handle) + "." + locale.toString(); SyndicationFeed feed = null; if (feedCache != null) { CacheFeed cFeed = feedCache.get(cacheKey); if (cFeed != null) // cache hit, but... { // Is the feed current? boolean cacheFeedCurrent = false; if (cFeed.timeStamp + (cacheAge * HOUR_MSECS) < System.currentTimeMillis()) { cacheFeedCurrent = true; } // Not current, but have any items changed since feed was created/last checked? else if (!itemsChanged(context, dso, cFeed.timeStamp)) { // no items have changed, re-stamp feed and use it cFeed.timeStamp = System.currentTimeMillis(); cacheFeedCurrent = true; } if (cacheFeedCurrent) { feed = cFeed.access(); } } } // either not caching, not found in cache, or feed in cache not current if (feed == null) { feed = new SyndicationFeed(SyndicationFeed.UITYPE_JSPUI); feed.populate(request, dso, getItems(context, dso), labelMap); if (feedCache != null) { cache(cacheKey, new CacheFeed(feed)); } } // set the feed to the requested type & return it try { feed.setType(feedType); response.setContentType("text/xml; charset=UTF-8"); feed.output(response.getWriter()); } catch (FeedException fex) { throw new IOException(fex.getMessage(), fex); } }
public static void main(String[] argv) throws Exception { // set headless for non-gui workstations System.setProperty("java.awt.headless", "true"); // create an options object and populate it CommandLineParser parser = new PosixParser(); Options options = new Options(); options.addOption( "v", "verbose", false, "print all extracted text and other details to STDOUT"); options.addOption("f", "force", false, "force all bitstreams to be processed"); options.addOption( "n", "noindex", false, "do NOT update the search index after filtering bitstreams"); options.addOption("i", "identifier", true, "ONLY process bitstreams belonging to identifier"); options.addOption("m", "maximum", true, "process no more than maximum items"); options.addOption("h", "help", false, "help"); CommandLine line = parser.parse(options, argv); if (line.hasOption('h')) { HelpFormatter myhelp = new HelpFormatter(); myhelp.printHelp("MediaFilter\n", options); System.exit(0); } if (line.hasOption('v')) { isVerbose = true; } if (line.hasOption('n')) { updateIndex = false; } if (line.hasOption('f')) { isForce = true; } if (line.hasOption('i')) { identifier = line.getOptionValue('i'); } if (line.hasOption('m')) { max2Process = Integer.parseInt(line.getOptionValue('m')); if (max2Process <= 1) { System.out.println("Invalid maximum value '" + line.getOptionValue('m') + "' - ignoring"); max2Process = Integer.MAX_VALUE; } } // set up filters filterClasses = (MediaFilter[]) PluginManager.getPluginSequence(MediaFilter.class); for (int i = 0; i < filterClasses.length; i++) { String filterName = filterClasses[i].getClass().getName(); String formats = ConfigurationManager.getProperty("filter." + filterName + ".inputFormats"); if (formats != null) { filterFormats.put(filterName, Arrays.asList(formats.split(",[\\s]*"))); } } Context c = null; try { c = new Context(); // have to be super-user to do the filtering c.setIgnoreAuthorization(true); // now apply the filters if (identifier == null) { applyFiltersAllItems(c); } else // restrict application scope to identifier { DSpaceObject dso = HandleManager.resolveToObject(c, identifier); if (dso == null) { throw new IllegalArgumentException( "Cannot resolve " + identifier + " to a DSpace object"); } switch (dso.getType()) { case Constants.COMMUNITY: applyFiltersCommunity(c, (Community) dso); break; case Constants.COLLECTION: applyFiltersCollection(c, (Collection) dso); break; case Constants.ITEM: applyFiltersItem(c, (Item) dso); break; } } // update search index? if (updateIndex) { System.out.println("Updating search index:"); DSIndexer.updateIndex(c); } c.complete(); c = null; } finally { if (c != null) { c.abort(); } } }
/** * Fills in the feed and entry-level metadata from DSpace objects. * * @param request request * @param context context * @param dso DSpaceObject * @param items array of objects * @param labels label map */ public void populate( HttpServletRequest request, Context context, DSpaceObject dso, List<? extends DSpaceObject> items, Map<String, String> labels) { String logoURL = null; String objectURL = 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.getName(); feed.setDescription(collectionService.getMetadata(col, "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.getName(); feed.setDescription(communityService.getMetadata(comm, "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()); StringBuffer db = new StringBuffer(); 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\\)", ""); } List<MetadataValue> dcv = itemService.getMetadataByMetadataString(item, df); if (dcv.size() > 0) { String fieldLabel = labels.get(MSG_METADATA + df); if (fieldLabel != null && fieldLabel.length() > 0) { db.append(fieldLabel).append(": "); } boolean first = true; for (MetadataValue v : dcv) { if (first) { first = false; } else { db.append("; "); } db.append(isDate ? new DCDate(v.getValue()).toString() : v.getValue()); } 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 List<MetadataValue> authors = itemService.getMetadataByMetadataString(item, authorField); if (authors.size() > 0) { List<SyndPerson> creators = new ArrayList<SyndPerson>(); for (MetadataValue author : authors) { SyndPerson sp = new SyndPersonImpl(); sp.setName(author.getValue()); 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) { List<MetadataValue> dcAuthors = itemService.getMetadataByMetadataString(item, dcCreatorField); if (dcAuthors.size() > 0) { List<String> creators = new ArrayList<String>(); for (MetadataValue author : dcAuthors) { creators.add(author.getValue()); } dc.setCreators(creators); } } if (dcDateField != null && !hasDate) { List<MetadataValue> v = itemService.getMetadataByMetadataString(item, dcDateField); if (v.size() > 0) { dc.setDate((new DCDate(v.get(0).getValue())).toDate()); } } if (dcDescriptionField != null) { List<MetadataValue> v = itemService.getMetadataByMetadataString(item, dcDescriptionField); if (v.size() > 0) { StringBuffer descs = new StringBuffer(); for (MetadataValue d : v) { if (descs.length() > 0) { descs.append("\n\n"); } descs.append(d.getValue()); } dc.setDescription(descs.toString()); } } entry.getModules().add(dc); } // iTunes Podcast Support - START if (podcastFeed) { // Add enclosure(s) List<SyndEnclosure> enclosures = new ArrayList(); try { List<Bundle> bunds = itemService.getBundles(item, "ORIGINAL"); if (bunds.get(0) != null) { List<Bitstream> bits = bunds.get(0).getBitstreams(); for (Bitstream bit : bits) { String mime = bit.getFormat(context).getMIMEType(); if (ArrayUtils.contains(podcastableMIMETypes, mime)) { SyndEnclosure enc = new SyndEnclosureImpl(); enc.setType(bit.getFormat(context).getMIMEType()); enc.setLength(bit.getSize()); enc.setUrl(urlOfBitstream(request, bit)); 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 List<MetadataValue> externalMedia = itemService.getMetadataByMetadataString(item, externalSourceField); if (externalMedia.size() > 0) { for (MetadataValue anExternalMedia : externalMedia) { 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(anExternalMedia.getValue()); 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); } }
public void processDSpaceObject( Context context, HttpServletRequest request, HttpServletResponse response, DSpaceObject dso, String extraPathInfo) throws ServletException, IOException, SQLException, AuthorizeException { // OK, we have a valid URI. What is it? if (dso.getType() == Constants.BITSTREAM) { // FIXME: Check for if-modified-since header Bitstream bitstream = (Bitstream) dso; log.info( LogManager.getHeader(context, "view_bitstream", "bitstream_id=" + bitstream.getID())); // Pipe the bits // InputStream is = bitstream.retrieve(); InputStream is = BitstreamStorageManager.retrieve(context, bitstream); // Set the response MIME type response.setContentType(bitstream.getFormat().getMIMEType()); response.setHeader("Content-Length", String.valueOf(bitstream.getSize())); response.setHeader("Content-disposition", "attachment; filename=" + bitstream.getName()); Utils.bufferedCopy(is, response.getOutputStream()); is.close(); response.getOutputStream().flush(); } else if (dso.getType() == Constants.ITEM) { Item item = (Item) dso; response.setDateHeader("Last-Modified", item.getLastModified().getTime()); // Check for if-modified-since header long modSince = request.getDateHeader("If-Modified-Since"); if (modSince != -1 && item.getLastModified().getTime() < modSince) { // Item has not been modified since requested date, // hence bitstream has not; return 304 response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } else { // Display the item page displayItem(context, request, response, item); } } else if (dso.getType() == Constants.COLLECTION) { Collection c = (Collection) dso; // Store collection location in request request.setAttribute("dspace.collection", c); /* * Find the "parent" community the collection, mainly for * "breadcrumbs" FIXME: At the moment, just grab the first community * the collection is in. This should probably be more context * sensitive when we have multiple inclusion. */ Community[] parents = (Community[]) c.getCommunities().toArray(); request.setAttribute("dspace.community", parents[0]); /* * Find all the "parent" communities for the collection for * "breadcrumbs" */ request.setAttribute("dspace.communities", getParents(parents[0], true)); // home page, or forward to another page? if ((extraPathInfo == null) || (extraPathInfo.equals("/"))) { collectionHome(context, request, response, parents[0], c); } else { // Forward to another servlet request.getRequestDispatcher(extraPathInfo).forward(request, response); } } else if (dso.getType() == Constants.COMMUNITY) { Community c = (Community) dso; // Store collection location in request request.setAttribute("dspace.community", c); /* * Find all the "parent" communities for the community */ request.setAttribute("dspace.communities", getParents(c, false)); // home page, or forward to another page? if ((extraPathInfo == null) || (extraPathInfo.equals("/"))) { communityHome(context, request, response, c); } else { // Forward to another servlet request.getRequestDispatcher(extraPathInfo).forward(request, response); } } else { // Shouldn't happen. Log and treat as invalid ID log.info( LogManager.getHeader( context, "URI not an item, collection or community", "identifier=" + dso.getIdentifier().toString())); JSPManager.showInvalidIDError(request, response, request.getPathInfo(), -1); return; } }
@Override public void authorizeAction( Context c, EPerson e, DSpaceObject o, int action, boolean useInheritance) throws AuthorizeException, SQLException { if (o == null) { // action can be -1 due to a null entry String actionText; if (action == -1) { actionText = "null"; } else { actionText = Constants.actionText[action]; } UUID userid; if (e == null) { userid = null; } else { userid = e.getID(); } throw new AuthorizeException( "Authorization attempted on null DSpace object " + actionText + " by user " + userid); } if (!authorize(c, o, action, e, useInheritance)) { // denied, assemble and throw exception int otype = o.getType(); UUID oid = o.getID(); UUID userid; if (e == null) { userid = null; } else { userid = e.getID(); } // AuthorizeException j = new AuthorizeException("Denied"); // j.printStackTrace(); // action can be -1 due to a null entry String actionText; if (action == -1) { actionText = "null"; } else { actionText = Constants.actionText[action]; } throw new AuthorizeException( "Authorization denied for action " + actionText + " on " + Constants.typeText[otype] + ":" + oid + " by user " + userid, o, action); } }