/* * MetadataExposure.java * * Version: $Revision: 3734 $ * * Date: $Date: 2009-04-24 00:00:19 -0400 (Fri, 24 Apr 2009) $ * * Copyright (c) 2002-2009, The DSpace Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of the DSpace Foundation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ package org.dspace.app.util; import java.util.Map; import java.util.Set; import java.util.HashMap; import java.util.HashSet; import java.util.Enumeration; import java.sql.SQLException; import org.apache.log4j.Logger; import org.dspace.authorize.AuthorizeManager; import org.dspace.core.Constants; import org.dspace.core.ConfigurationManager; import org.dspace.core.Context; /** * Static utility class to manage configuration for exposure (hiding) of * certain Item metadata fields. * * This class answers the question, "is the user allowed to see this * metadata field?" Any external interface (UI, OAI-PMH, etc) that * disseminates metadata should consult it before disseminating the value * of a metadata field. * * Since the MetadataExposure.isHidden() method gets called in a lot of inner * loops, it is important to implement it efficiently, in both time and * memory utilization. It computes an answer without consuming ANY memory * (e.g. it does not build any temporary Strings) and in close to constant * time by use of hash tables. Although most sites will only hide a few * fields, we can't predict what the usage will be so it's better to make it * scalable. * * Algorithm is as follows: * 1. If a Context is provided and it has a user who is Administrator, * always grant access (return false). * 2. Return true if field is on the hidden list, false otherwise. * * The internal maps are populated from DSpace Configuration at the first * call, in case the properties are not available in the static context. * * Configuration Properties: * ## hide a single metadata field * #metadata.hide.SCHEMA.ELEMENT[.QUALIFIER] = true * # example: dc.type * metadata.hide.dc.type = true * # example: dc.description.provenance * metadata.hide.dc.description.provenance = true * * @author Larry Stone * @version $Revision: 3734 $ */ public class MetadataExposure { private static Logger log = Logger.getLogger(MetadataExposure.class); private static Map<String,Set<String>> hiddenElementSets = null; private static Map<String,Map<String,Set<String>>> hiddenElementMaps = null; private static final String CONFIG_PREFIX = "metadata.hide."; public static boolean isHidden(Context context, String schema, String element, String qualifier) throws SQLException { // the administrator's override if (context != null && AuthorizeManager.isAdmin(context)) return false; // for schema.element, just check schema->elementSet init(); if (qualifier == null) { Set<String> elts = hiddenElementSets.get(schema); return elts == null ? false : elts.contains(element); } // for schema.element.qualifier, just schema->eltMap->qualSet else { Map<String,Set<String>> elts = hiddenElementMaps.get(schema); if (elts == null) return false; Set<String> quals = elts.get(element); return quals == null ? false : quals.contains(qualifier); } } // load maps from configuration unless it's already done. private static void init() { if (hiddenElementSets == null) { hiddenElementSets = new HashMap<String,Set<String>>(); hiddenElementMaps = new HashMap<String,Map<String,Set<String>>>(); Enumeration pne = ConfigurationManager.propertyNames(); while (pne.hasMoreElements()) { String key = (String)pne.nextElement(); if (key.startsWith(CONFIG_PREFIX)) { String mdField = key.substring(CONFIG_PREFIX.length()); String segment[] = mdField.split("\\.", 3); // got schema.element.qualifier if (segment.length == 3) { Map<String,Set<String>> eltMap = hiddenElementMaps.get(segment[0]); if (eltMap == null) { eltMap = new HashMap<String,Set<String>>(); hiddenElementMaps.put(segment[0], eltMap); } if (!eltMap.containsKey(segment[1])) { eltMap.put(segment[1], new HashSet<String>()); } eltMap.get(segment[1]).add(segment[2]); } // got schema.element else if (segment.length == 2) { if (!hiddenElementSets.containsKey(segment[0])) { hiddenElementSets.put(segment[0], new HashSet<String>()); } hiddenElementSets.get(segment[0]).add(segment[1]); } // oops.. else { log.warn("Bad format in hidden metadata directive, field=\""+mdField+"\", config property="+key); } } } } } }