/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package fedora.server.validation;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.log4j.Logger;
import fedora.common.FaultException;
import fedora.common.PID;
import fedora.server.errors.ServerException;
import fedora.server.errors.ValidationException;
import fedora.server.security.PolicyParser;
import fedora.server.storage.DOReader;
import fedora.server.storage.types.Datastream;
import fedora.server.storage.types.DatastreamManagedContent;
/**
* Misc validation-related functions.
*
* @author Chris Wilper
* @author Edwin Shin
* @version $Id$
*/
public abstract class ValidationUtility {
private static final Logger LOG = Logger.getLogger(ValidationUtility.class);
private static PolicyParser policyParser;
/**
* Validates the candidate URL. The result of the validation also depends on the
* control group of the datastream in question. Managed datastreams may be ingested
* using the file URI scheme, other datastreams may not.
*
* @param url
* The URL to validate.
* @param controlGroup
* The control group of the datastream the URL belongs to.
*
* @throws ValidationException
* if the URL is malformed.
*/
public static void validateURL(String url, String controlGroup)
throws ValidationException {
if (!(controlGroup.equalsIgnoreCase("M") || controlGroup.equalsIgnoreCase("E")) && url.startsWith("file:")) {
throw new ValidationException(
"Malformed URL (file: not allowed for control group "
+ controlGroup + ") " + url);
}
try {
new URL(url);
} catch (MalformedURLException e) {
if (url.startsWith(DatastreamManagedContent.UPLOADED_SCHEME)) {
return;
}
throw new ValidationException("Malformed URL: " + url, e);
}
}
/**
* Sets the policy parser to be used to validate "POLICY" datastream.
*
* NOTE: This must be set before attempting to validate POLICY datastreams.
* Otherwise, a runtime exception will be thrown.
*
* @param parser the parser to use.
*/
public static void setPolicyParser(PolicyParser parser) {
policyParser = parser;
}
/**
* Validates the latest version of all reserved datastreams in the given
* object.
*/
public static void validateReservedDatastreams(DOReader reader)
throws ValidationException {
try {
for (Datastream ds: reader.GetDatastreams(null, null)) {
if ("X".equals(ds.DSControlGrp)) {
validateReservedDatastream(PID.getInstance(reader.GetObjectPID()),
ds.DatastreamID,
ds.getContentStream());
}
}
} catch (ValidationException e) {
throw e;
} catch (ServerException e) {
throw new FaultException(e);
}
}
/**
* Validates the given datastream if it's a reserved datastream.
*
* The given stream is guaranteed to be closed when this method completes.
*/
public static void validateReservedDatastream(PID pid,
String dsId,
InputStream content)
throws ValidationException {
if ("POLICY".equals(dsId)) {
validatePOLICY(content);
} else if ("RELS-EXT".equals(dsId) || "RELS-INT".equals(dsId)) {
validateRELS(pid, dsId, content);
} else {
try {
content.close();
} catch (IOException e) {
LOG.warn("Error closing stream", e);
}
}
}
private static void validatePOLICY(InputStream content)
throws ValidationException {
LOG.debug("Validating POLICY datastream");
policyParser.copy().parse(content, true);
LOG.debug("POLICY datastream is valid");
}
/**
* validate relationships datastream
* @param pid
* @param dsId
* @param content
* @throws ValidationException
*/
private static void validateRELS(PID pid, String dsId, InputStream content)
throws ValidationException {
LOG.debug("Validating " + dsId + " datastream");
new RelsValidator().validate(pid, dsId, content);
LOG.debug(dsId + " datastream is valid");
}
}