/* 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.access.defaultdisseminator;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import fedora.common.Constants;
import fedora.common.Models;
import fedora.server.Context;
import fedora.server.access.Access;
import fedora.server.access.ObjectProfile;
import fedora.server.errors.DisseminationException;
import fedora.server.errors.GeneralException;
import fedora.server.errors.ObjectIntegrityException;
import fedora.server.errors.ServerException;
import fedora.server.storage.DOReader;
import fedora.server.storage.types.DatastreamXMLMetadata;
import fedora.server.storage.types.MIMETypedStream;
import fedora.server.storage.types.MethodDef;
import fedora.server.storage.types.MethodParmDef;
import fedora.server.storage.types.ObjectMethodsDef;
import fedora.utilities.XmlTransformUtility;
/**
* Implements the methods defined in the DefaultDisseminator interface. This is
* the default Service Deployment that implements the "contract" of the default
* Service Definition that is dynamically associated with every digital object
* in the repository. This class is considered an "internal service" that is
* built in to the Fedora system. Its purpose is to endow every digital object
* with a set of generic behaviors. It is an implementation of what is known as
* the Default Disseminator. Unlike other Service Definitions and Deployments,
* there is no Service Definition Object or Service Deployment Object stored in
* the repository.
*
* @author Sandy Payette
* @version $Id: DefaultDisseminatorImpl.java 7973 2009-04-21 22:03:40Z kstrnad
* $
*/
public class DefaultDisseminatorImpl
extends InternalService
implements DefaultDisseminator {
private final Context context;
private final Date asOfDateTime;
private final DOReader reader;
private final String reposBaseURL;
private final File reposHomeDir;
private final Access m_access;
public DefaultDisseminatorImpl(Context context,
Date asOfDateTime,
DOReader reader,
Access access,
String reposBaseURL,
File reposHomeDir)
throws ServerException {
this.context = context;
this.asOfDateTime = asOfDateTime;
this.reader = reader;
m_access = access;
this.reposBaseURL = reposBaseURL;
this.reposHomeDir = reposHomeDir;
}
/**
* Returns an HTML rendering of the object profile which contains key
* metadata from the object, plus URLs for the object's Dissemination Index
* and Item Index. The data is returned as HTML in a presentation-oriented
* format. This is accomplished by doing an XSLT transform on the XML that
* is obtained from getObjectProfile in API-A.
*
* @return html packaged as a MIMETypedStream
* @throws ServerException
*/
public MIMETypedStream viewObjectProfile() throws ServerException {
try {
ObjectProfile profile =
m_access.getObjectProfile(context,
reader.GetObjectPID(),
asOfDateTime);
InputStream in = null;
try {
in =
new ByteArrayInputStream(new ObjectInfoAsXML()
.getObjectProfile(reposBaseURL,
profile,
asOfDateTime)
.getBytes("UTF-8"));
} catch (UnsupportedEncodingException uee) {
throw new GeneralException("[DefaultDisseminatorImpl] An error has occurred. "
+ "The error was a \""
+ uee.getClass().getName()
+ "\" . The "
+ "Reason was \""
+ uee.getMessage()
+ "\" .");
}
//InputStream in = getObjectProfile().getStream();
ByteArrayOutputStream out = new ByteArrayOutputStream();
File xslFile =
new File(reposHomeDir, "access/viewObjectProfile.xslt");
TransformerFactory factory =
XmlTransformUtility.getTransformerFactory();
Templates template =
factory.newTemplates(new StreamSource(xslFile));
Transformer transformer = template.newTransformer();
transformer.setParameter("fedora", context
.getEnvironmentValue(Constants.FEDORA_APP_CONTEXT_NAME));
transformer.transform(new StreamSource(in), new StreamResult(out));
in = new ByteArrayInputStream(out.toByteArray());
return new MIMETypedStream("text/html", in, null);
} catch (TransformerException e) {
throw new DisseminationException("[DefaultDisseminatorImpl] had an error "
+ "in transforming xml for viewObjectProfile. "
+ "Underlying exception was: " + e.getMessage());
}
}
/**
* Returns an HTML rendering of the Dissemination Index for the object. The
* Dissemination Index is a list of method definitions that represent all
* disseminations possible on the object. The Dissemination Index is
* returned as HTML in a presentation-oriented format. This is accomplished
* by doing an XSLT transform on the XML that is obtained from listMethods
* in API-A.
*
* @return html packaged as a MIMETypedStream
* @throws ServerException
*/
public MIMETypedStream viewMethodIndex() throws ServerException {
// sdp: the dissemination index is disabled for service definition and deployment objects
// so send back a message saying so.
if (reader.hasContentModel(Models.SERVICE_DEFINITION_3_0)
|| reader.hasContentModel(Models.SERVICE_DEPLOYMENT_3_0)) {
return noMethodIndexMsg();
}
// get xml expression of method definitions
ObjectMethodsDef[] methods =
m_access.listMethods(context,
reader.GetObjectPID(),
asOfDateTime);
InputStream in = null;
try {
in =
new ByteArrayInputStream(new ObjectInfoAsXML()
.getMethodIndex(reposBaseURL,
reader.GetObjectPID(),
methods,
asOfDateTime).getBytes("UTF-8"));
} catch (UnsupportedEncodingException uee) {
throw new GeneralException("[DefaultDisseminatorImpl] An error has occurred. "
+ "The error was a \""
+ uee.getClass().getName()
+ "\" . The "
+ "Reason was \""
+ uee.getMessage()
+ "\" .");
}
// transform the method definitions xml to an html view
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
File xslFile =
new File(reposHomeDir, "access/listMethods.xslt");
TransformerFactory factory =
XmlTransformUtility.getTransformerFactory();
Templates template =
factory.newTemplates(new StreamSource(xslFile));
Transformer transformer = template.newTransformer();
transformer.setParameter("fedora", context
.getEnvironmentValue(Constants.FEDORA_APP_CONTEXT_NAME));
transformer.transform(new StreamSource(in), new StreamResult(out));
in = new ByteArrayInputStream(out.toByteArray());
return new MIMETypedStream("text/html", in, null);
} catch (TransformerException e) {
throw new DisseminationException("[DefaultDisseminatorImpl] had an error "
+ "in transforming xml for viewItemIndex. "
+ "Underlying exception was: " + e.getMessage());
}
}
/**
* Returns an HTML rendering of the Item Index for the object. The Item
* Index is a list of all datastreams in the object. The datastream items
* can be data or metadata. The Item Index is returned as HTML in a
* presentation-oriented format. This is accomplished by doing an XSLT
* transform on the XML that is obtained from listDatastreams in API-A.
*
* @return html packaged as a MIMETypedStream
* @throws ServerException
*/
public MIMETypedStream viewItemIndex() throws ServerException {
// get the item index as xml
InputStream in = null;
try {
in =
new ByteArrayInputStream(new ObjectInfoAsXML()
.getItemIndex(reposBaseURL,
context
.getEnvironmentValue(Constants.FEDORA_APP_CONTEXT_NAME),
reader,
asOfDateTime).getBytes("UTF-8"));
} catch (Exception e) {
throw new GeneralException("[DefaultDisseminatorImpl] An error has occurred. "
+ "The error was a \""
+ e.getClass().getName()
+ "\" . The " + "Reason was \"" + e.getMessage() + "\" .");
}
// convert the xml to an html view
try {
//InputStream in = getItemIndex().getStream();
ByteArrayOutputStream out = new ByteArrayOutputStream();
File xslFile = new File(reposHomeDir, "access/viewItemIndex.xslt");
TransformerFactory factory =
XmlTransformUtility.getTransformerFactory();
Templates template =
factory.newTemplates(new StreamSource(xslFile));
Transformer transformer = template.newTransformer();
transformer.setParameter("fedora", context
.getEnvironmentValue(Constants.FEDORA_APP_CONTEXT_NAME));
transformer.transform(new StreamSource(in), new StreamResult(out));
in = new ByteArrayInputStream(out.toByteArray());
return new MIMETypedStream("text/html", in, null);
} catch (TransformerException e) {
throw new DisseminationException("[DefaultDisseminatorImpl] had an error "
+ "in transforming xml for viewItemIndex. "
+ "Underlying exception was: " + e.getMessage());
}
}
/**
* Returns the Dublin Core record for the object, if one exists. The record
* is returned as HTML in a presentation-oriented format.
*
* @return html packaged as a MIMETypedStream
* @throws ServerException
*/
public MIMETypedStream viewDublinCore() throws ServerException {
// get dublin core record as xml
DatastreamXMLMetadata dcmd = null;
InputStream in = null;
try {
dcmd =
(DatastreamXMLMetadata) reader.GetDatastream("DC",
asOfDateTime);
in =
new ByteArrayInputStream(new ObjectInfoAsXML()
.getOAIDublinCore(dcmd).getBytes("UTF-8"));
} catch (ClassCastException cce) {
throw new ObjectIntegrityException("Object "
+ reader.GetObjectPID()
+ " has a DC datastream, but it's not inline XML.");
} catch (UnsupportedEncodingException uee) {
throw new GeneralException("[DefaultDisseminatorImpl] An error has occurred. "
+ "The error was a \""
+ uee.getClass().getName()
+ "\" . The "
+ "Reason was \""
+ uee.getMessage()
+ "\" .");
}
// convert the dublin core xml to an html view
try {
//InputStream in = getDublinCore().getStream();
ByteArrayOutputStream out = new ByteArrayOutputStream();
File xslFile = new File(reposHomeDir, "access/viewDublinCore.xslt");
TransformerFactory factory =
XmlTransformUtility.getTransformerFactory();
Templates template =
factory.newTemplates(new StreamSource(xslFile));
Transformer transformer = template.newTransformer();
transformer.setParameter("fedora", context
.getEnvironmentValue(Constants.FEDORA_APP_CONTEXT_NAME));
transformer.transform(new StreamSource(in), new StreamResult(out));
in = new ByteArrayInputStream(out.toByteArray());
return new MIMETypedStream("text/html", in, null);
} catch (TransformerException e) {
throw new DisseminationException("[DefaultDisseminatorImpl] had an error "
+ "in transforming xml for viewDublinCore. "
+ "Underlying exception was: " + e.getMessage());
}
}
private MIMETypedStream noMethodIndexMsg() throws GeneralException {
String msg =
new String("The Dissemination Index is not available"
+ " for Content Model objects, \n or Service Definition objects or Service Deployment objects.\n"
+ " The addition of this feature is not currently scheduled.");
StringBuffer sb = new StringBuffer();
sb
.append("<html><head><title>Dissemination Index Not Available</title></head>");
sb.append("<body><center>");
sb
.append("<table width=\"784\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">");
sb
.append("<tr><td width=\"141\" height=\"134\" valign=\"top\"><img src=\"/")
.append(context
.getEnvironmentValue(Constants.FEDORA_APP_CONTEXT_NAME))
.append("/images/newlogo2.jpg\" width=\"141\" height=\"134\"/></td>");
sb.append("<td width=\"643\" valign=\"top\">");
sb.append("<center><h2>Fedora Repository</h2>");
sb.append("<h3>Dissemination Index</h3>");
sb.append("</center></td></tr></table>");
sb.append("<p>" + msg + "</p>");
sb.append("</body>");
sb.append("</html>");
String msgOut = sb.toString();
ByteArrayInputStream in = null;
try {
in = new ByteArrayInputStream(msgOut.getBytes("UTF-8"));
} catch (UnsupportedEncodingException uee) {
throw new GeneralException("[DefaultDisseminatorImpl] An error has occurred. "
+ "The error was a \""
+ uee.getClass().getName()
+ "\" . The "
+ "Reason was \""
+ uee.getMessage()
+ "\" .");
}
return new MIMETypedStream("text/html", in, null);
}
/**
* Method implementation of reflectMethods from the InternalService
* interface. This will return an array of method definitions that
* constitute the behaviors of the Default Disseminator which is associated
* with every Fedora object. These will be the methods promulgated by the
* DefaultDisseminator interface.
*
* @return an array of method defintions
*/
public static MethodDef[] reflectMethods() {
ArrayList<MethodDef> methodList = new ArrayList<MethodDef>();
MethodDef method = null;
method = new MethodDef();
method.methodName = "viewObjectProfile";
method.methodLabel = "View description of the object";
method.methodParms = new MethodParmDef[0];
methodList.add(method);
method = new MethodDef();
method.methodName = "viewMethodIndex";
method.methodLabel =
"View a list of dissemination methods in the object";
method.methodParms = new MethodParmDef[0];
methodList.add(method);
method = new MethodDef();
method.methodName = "viewItemIndex";
method.methodLabel = "View a list of items in the object";
method.methodParms = new MethodParmDef[0];
methodList.add(method);
method = new MethodDef();
method.methodName = "viewDublinCore";
method.methodLabel = "View the Dublin Core record for the object";
method.methodParms = new MethodParmDef[0];
methodList.add(method);
return methodList.toArray(new MethodDef[0]);
}
}