package org.dspace.app.xmlui.cocoon; import org.dspace.app.xmlui.utils.ContextUtil; import org.dspace.app.xmlui.utils.HandleUtil; import org.dspace.core.Context; import org.dspace.core.ConfigurationManager; import org.dspace.usage.UsageEvent; import org.dspace.utils.DSpace; import org.dspace.content.DSpaceObject; import org.dspace.content.Bitstream; import org.dspace.content.Item; import org.dspace.content.Bundle; import org.dspace.handle.HandleManager; import org.apache.cocoon.environment.Request; import org.apache.cocoon.environment.ObjectModelHelper; import org.apache.cocoon.environment.Redirector; import org.apache.cocoon.environment.SourceResolver; import org.apache.cocoon.acting.AbstractAction; import org.apache.avalon.framework.parameters.Parameters; import java.sql.SQLException; import java.util.Map; import javax.servlet.http.HttpServletRequest; /** * Created by IntelliJ IDEA. * User: kevinvandevelde * Date: 22-dec-2008 * Time: 15:00:55 * To change this template use File | Settings | File Templates. */ public class UsageLoggerAction extends AbstractAction { public Map act(Redirector redirector, SourceResolver sourceResolver, Map objectModel, String string, Parameters parameters) throws Exception { try{ Request request = ObjectModelHelper.getRequest(objectModel); Context context = ContextUtil.obtainContext(objectModel); DSpaceObject dso = HandleUtil.obtainHandle(objectModel); if(dso == null){ //We might have a bitstream dso = findBitstream(context, parameters); } logDspaceObject(request, dso, context); }catch(Exception e){ //Ignore we cannot let this crash //TODO: log this e.printStackTrace(); } // Finished, allow to pass. return null; } public static void logDspaceObject(Request request, DSpaceObject dso, Context context){ if(dso == null) return; try { new DSpace().getEventService().fireEvent( new UsageEvent( UsageEvent.Action.VIEW, (HttpServletRequest)request, ContextUtil.obtainContext((HttpServletRequest)request), dso)); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private Bitstream findBitstream(Context context, Parameters par) throws SQLException { // Get our parameters that identify the bitstream int itemID = par.getParameterAsInteger("itemID", -1); int bitstreamID = par.getParameterAsInteger("bitstreamID", -1); String handle = par.getParameter("handle", null); int sequence = par.getParameterAsInteger("sequence", -1); String name = par.getParameter("name", null); // Reslove the bitstream Bitstream bitstream = null; Item item; DSpaceObject dso; if (bitstreamID > -1) { // Direct refrence to the individual bitstream ID. bitstream = Bitstream.find(context, bitstreamID); } else if (itemID > -1) { // Referenced by internal itemID item = Item.find(context, itemID); if (sequence > -1) { bitstream = findBitstreamBySequence(item, sequence); } else if (name != null) { bitstream = findBitstreamByName(item, name); } } else if (handle != null) { // Reference by an item's handle. dso = HandleManager.resolveToObject(context,handle); if (dso instanceof Item) { item = (Item)dso; if (sequence > -1) { bitstream = findBitstreamBySequence(item,sequence); } else if (name != null) { bitstream = findBitstreamByName(item,name); } } } return bitstream; } /** * Find the bitstream identified by a sequence number on this item. * * @param item A DSpace item * @param sequence The sequence of the bitstream * @return The bitstream or null if none found. */ private Bitstream findBitstreamBySequence(Item item, int sequence) throws SQLException { if (item == null) return null; Bundle[] bundles = item.getBundles(); for (Bundle bundle : bundles) { Bitstream[] bitstreams = bundle.getBitstreams(); for (Bitstream bitstream : bitstreams) { if (bitstream.getSequenceID() == sequence) { return bitstream; } } } return null; } /** * Return the bitstream from the given item that is identified by the * given name. If the name has prepended directories they will be removed * one at a time until a bitstream is found. Note that if two bitstreams * have the same name then the first bitstream will be returned. * * @param item A DSpace item * @param name The name of the bitstream * @return The bitstream or null if none found. */ private Bitstream findBitstreamByName(Item item, String name) throws SQLException { if (name == null || item == null) return null; // Determine our the maximum number of directories that will be removed for a path. int maxDepthPathSearch = 3; if (ConfigurationManager.getProperty("xmlui.html.max-depth-guess") != null) maxDepthPathSearch = ConfigurationManager.getIntProperty("xmlui.html.max-depth-guess"); // Search for the named bitstream on this item. Each time through the loop // a directory is removed from the name until either our maximum depth is // reached or the bitstream is found. Note: an extra pass is added on to the // loop for a last ditch effort where all directory paths will be removed. for (int i = 0; i < maxDepthPathSearch+1; i++) { // Search through all the bitstreams and see // if the name can be found Bundle[] bundles = item.getBundles(); for (Bundle bundle : bundles) { Bitstream[] bitstreams = bundle.getBitstreams(); for (Bitstream bitstream : bitstreams) { if (name.equals(bitstream.getName())) { return bitstream; } } } // The bitstream was not found, so try removing a directory // off of the name and see if we lost some path information. int indexOfSlash = name.indexOf('/'); if (indexOfSlash < 0) // No more directories to remove from the path, so return null for no // bitstream found. return null; name = name.substring(indexOfSlash+1); // If this is our next to last time through the loop then // trim everything and only use the trailing filename. if (i == maxDepthPathSearch-1) { int indexOfLastSlash = name.lastIndexOf('/'); if (indexOfLastSlash > -1) name = name.substring(indexOfLastSlash+1); } } // The named bitstream was not found and we exausted our the maximum path depth that // we search. return null; } }