/*
* IIIFServerBridge.java
* Copyright (C) 2018 New Zealand Digital Library, http://www.nzdl.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.greenstone.gsdl3;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.greenstone.gsdl3.comms.Communicator;
import org.greenstone.gsdl3.comms.SOAPCommunicator;
import org.greenstone.gsdl3.core.IIIFMessageRouter;
import org.greenstone.gsdl3.core.IIIFReceptionist;
import org.greenstone.gsdl3.util.GSConstants;
import org.greenstone.gsdl3.util.GSParams;
import org.greenstone.gsdl3.util.GSXML;
import org.greenstone.gsdl3.util.IIIFXML;
import org.greenstone.gsdl3.util.XMLConverter;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/** a class the serve as a bridge between the Cantaloupe IIIF image server and
* Greenstone collections. Loosely based on OAIServer
*
* the init method is called only once - the first time the bridge is established
* then doGet() each time a document image request is made
* @see Receptionist
*/
/**
* IIIF server configuration instructions *
*
*/
public class IIIFServerBridge
{
/** the receptionist to send messages to */
protected IIIFReceptionist recept = null;
/**
* The name of the site with which we will finally be dealing, whether it is
* a local site or a remote site through a communicator.
*/
protected String site = "";
static Logger logger = Logger.getLogger(org.greenstone.gsdl3.IIIFServerBridge.class.getName());
private void configure() throws UnavailableException
{
// Read in IIIFConfig.xml (residing web/WEB-INF/classes/) and
//use it to configure the receptionist.
Element iiif_config = IIIFXML.getIIIFConfigXML();
if (iiif_config == null)
{
logger.error("Fail to parse IIIF config file IIIFConfig.xml.");
throw new UnavailableException("IIIFServerBridge: Couldn't parse IIIFConfig.xml");
}
// pass it to the receptionist
if (!this.recept.configure(iiif_config)) {
logger.error("Couldn't configure IIIF receptionist");
throw new UnavailableException("IIIFServerBridge: Couldn't configure receptionist");
}
}
/**
* initialise the class
*/
public void init(String site_name) throws UnavailableException, Exception
{
org.greenstone.util.GlobalProperties.loadGlobalProperties("");
java.io.InputStream in = Class.forName("org.greenstone.util.GlobalProperties").getClassLoader().getResourceAsStream("global.properties");
String tomcat_context = System.getProperty("tomcat.context");
// the receptionist -the servlet will talk to this
this.recept = new IIIFReceptionist();
//this site_name could consist of comma separated more than one site name.
IIIFMessageRouter message_router = new IIIFMessageRouter();
message_router.setSiteName(site_name);
// lots of work is done in this step; see IIIFMessageRouter.java
if (!message_router.configure()) {
throw new UnavailableException("IIIFServerBridge: Couldn't configure IIIFMessageRouter");
}
this.recept.setSiteName(site_name);
this.recept.setMessageRouter(message_router);
configure();
} // end of init()
/*
Written but never used/tested
*/
public void remote_init(String remote_site_name, String remote_site_type, String remote_site_address) throws UnavailableException
{
if (remote_site_name == null || remote_site_type == null || remote_site_address == null)
{
logger.error("Initialisation paramters not all set!");
logger.error("You must have remote_site_name, remote_site_type and remote_site_address set");
throw new UnavailableException("IIIFServerBridge: incorrect remote connection parameters specified");
}
// the receptionist -the servlet will talk to this
this.recept = new IIIFReceptionist();
// talking to a remote site, create a communicator
Communicator communicator = null;
// we need to create the XML to configure the communicator
Document site_doc = XMLConverter.newDOM();
Element site_elem = site_doc.createElement(GSXML.SITE_ELEM);
site_elem.setAttribute(GSXML.TYPE_ATT, remote_site_type);
site_elem.setAttribute(GSXML.NAME_ATT, remote_site_name);
site_elem.setAttribute(GSXML.ADDRESS_ATT, remote_site_address);
if (remote_site_type.equals(GSXML.COMM_TYPE_SOAP_JAVA))
{
communicator = new SOAPCommunicator();
}
else
{
logger.error("IIIFServerBridge.init Error: invalid Communicator type: " + remote_site_type);
throw new UnavailableException("IIIFServerBridge: invalid communicator type");
}
if (!communicator.configure(site_elem))
{
logger.error("IIIFServerBridge.init Error: Couldn't configure communicator");
throw new UnavailableException("IIIFServerBridge: Couldn't configure communicator");
}
this.recept.setSiteName(remote_site_name);
this.recept.setMessageRouter(communicator);
configure();
} // end of remote_init()
public String doGetDocumentMessage(String identifier)
{
String result = "";
String[] pairs = new String[2];
pairs[0] = "verb=GetRecord";
pairs[1] = "identifier="+identifier;
String verb = "GetRecord";
Document response_doc = XMLConverter.newDOM();
//Element xml_response = IIIFXML.createBasicResponse(response_doc, verb, pairs);
//Element verb_elem = null;
// compose the request message to the receptionist
Document request_doc = XMLConverter.newDOM();
Element xml_message = request_doc.createElement(GSXML.MESSAGE_ELEM);
Element xml_request = request_doc.createElement(GSXML.REQUEST_ELEM);
xml_request.setAttribute(GSXML.TO_ATT, verb);
addParams(xml_request, pairs);
xml_message.appendChild(xml_request);
Node xml_result = this.recept.process(xml_message);
if (xml_result == null)
{
logger.error("xml_result is null");
//verb_elem = IIIFXML.createErrorElement(response_doc, "Internal error", "");
//xml_response.appendChild(verb_elem);
}
else
{
//
// All response elements are in the form (with a corresponding verb
// name): ...
//
Node res = GSXML.getChildByTagName(xml_result, GSXML.RESPONSE_ELEM);
if (res == null)
{
logger.error("response element in xml_result is null");
//verb_elem = IIIFXML.createErrorElement(response_doc, "Internal error", "");
}
else {
Element verb_elem = GSXML.getFirstElementChild(res); // GetRecord
Node record_node = GSXML.getFirstElementChild(verb_elem); // record
Element metadata_list_elem = (Element)GSXML.getChildByTagName(record_node,"metadata"); // metadata
Element assocfilepath_metadata_elem = (Element)GSXML.getChildByTagName(metadata_list_elem,"assocfilepath");
if (assocfilepath_metadata_elem == null) {
logger.error("Failed to find metadata 'assocfilepath' for Document " + identifier);
//verb_elem = IIIFXML.createErrorElement(response_doc, "Internal error", "");
}
else {
String assocfilepath_metadata_val = GSXML.getNodeText(assocfilepath_metadata_elem);
Element image_metadata_elem = (Element)GSXML.getChildByTagName(metadata_list_elem,"Image");
if (assocfilepath_metadata_elem == null) {
logger.error("Failed to find metadata 'Image' for Document " + identifier);
}
else {
String image_metadata_val = GSXML.getNodeText(image_metadata_elem);
result = assocfilepath_metadata_val + "/" + image_metadata_val;
}
}
}
//xml_response.appendChild(response_doc.importNode(verb_elem, true));
}
return result;
}
/** append parameter elements to the request sent to the receptionist */
public void addParams(Element request, String[] pairs)
{
Document doc = request.getOwnerDocument();
// no params apart from the verb
if (pairs == null || pairs.length < 2)
return;
/**
* the request xml is composed in the form:
* (No paramList element in between).
*/
for (int i = 1; i < pairs.length; i++)
{
//the first pair in pairs is the verb=xxx
int index = pairs[i].indexOf("=");
if (index != -1)
{ //just a double check
Element param = GSXML.createParameter(doc, pairs[i].substring(0, index), IIIFXML.iiifDecode(pairs[i].substring(index + 1)));
request.appendChild(param);
}
}
}
public void destroy()
{
recept.cleanUp();
}
}