Package org.fcrepo.server.storage.service

Source Code of org.fcrepo.server.storage.service.ServiceMapper

/* 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 org.fcrepo.server.storage.service;

import java.io.File;
import java.io.FileInputStream;

import java.util.Vector;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import org.fcrepo.server.errors.GeneralException;
import org.fcrepo.server.errors.ObjectIntegrityException;
import org.fcrepo.server.errors.RepositoryConfigurationException;
import org.fcrepo.server.storage.types.DeploymentDSBindSpec;
import org.fcrepo.server.storage.types.MethodDef;
import org.fcrepo.server.storage.types.MethodDefOperationBind;
import org.fcrepo.server.storage.types.MethodParmDef;


/**
* Controller class for parsing the various kinds of inline metadata datastreams
* found in service objects. The intent of this class is to initiate parsing of
* these datastreams so that information about a service can be
* instantiated in Fedora.
* </p>
*
* @author Sandy Payette
* @version $Id$
*/
public class ServiceMapper {

    private WSDLParser wsdlHandler;

    private MmapParser methodMapHandler;

    private DSInputSpecParser dsInputSpecHandler;

    private final String parentPID;

    public static void main(String[] args) {
        if (args.length < 2) {
            System.err
                    .println("usage: java ServiceMapper wsdlLocation methodMapLocation "
                            + "\n"
                            + "  wsdlLocation: the file path of the wsdl to be parsed"
                            + "\n"
                            + "  methodMapLocation: the file path of the method map to be parsed."
                            + "\n"
                            + "  dsInputSpecLocation: the file path of the datastream input spec to be parsed."
                            + "  pid: the PID of the sDef or sDep object for the above files.");
            System.exit(1);
        }
        try {
            ServiceMapper mapper = new ServiceMapper(args[3]);
            InputSource wsdl =
                    new InputSource(new FileInputStream(new File(args[0])));
            InputSource mmap =
                    new InputSource(new FileInputStream(new File(args[1])));
            InputSource dsSpec =
                    new InputSource(new FileInputStream(new File(args[2])));
            mapper.getMethodDefs(mmap);
            mapper.getMethodDefBindings(wsdl, mmap);
            mapper.getDSInputSpec(dsSpec);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.exit(1);

    }

    public ServiceMapper(String behaviorObjectPID) {
        parentPID = behaviorObjectPID;
    }

    /**
     * getMethodDefs: creates an array of abstract method definitions in the
     * form of an array of Fedora MethodDef objects. The creation of a MethodDef
     * object requires information from a Fedora Method Map.
     *
     * @param methodMapSource :
     *        Fedora Method Map definition for methods
     * @return MethodDef[] : an array of abstract method definitions
     * @throws ObjectIntegrityException
     * @throws RepositoryConfigurationException
     * @throws GeneralException
     */
    public MethodDef[] getMethodDefs(InputSource methodMapSource)
            throws ObjectIntegrityException, RepositoryConfigurationException,
            GeneralException {
        Mmap methodMap = getMethodMap(methodMapSource);
        return methodMap.mmapMethods;
    }

    /**
     * getMethodDefBindings: creates an array of operation bindings in the form
     * of an array of Fedora MethodDefOperationBind objects. The creation of a
     * MethodDefOperationBind object requires information from a WSDL service
     * definition and a related Fedora Method Map. The Fedora Method Map is
     * merged with the WSDL to provide a Fedora-specific view of the WSDL.
     *
     * @param wsdlSource :
     *        WSDL service definition for methods
     * @param methodMapSource :
     *        Fedora Method Map definition for methods
     * @return MethodDefOperationBind[] : an array of method bindings
     * @throws ObjectIntegrityException
     * @throws RepositoryConfigurationException
     * @throws GeneralException
     */
    public MethodDefOperationBind[] getMethodDefBindings(InputSource wsdlSource,
                                                         InputSource methodMapSource)
            throws ObjectIntegrityException, RepositoryConfigurationException,
            GeneralException {
        return merge(getService(wsdlSource), getMethodMap(methodMapSource));
    }

    public DeploymentDSBindSpec getDSInputSpec(InputSource dsInputSpecSource)
            throws ObjectIntegrityException, RepositoryConfigurationException,
            GeneralException {
        if (dsInputSpecHandler == null) {
            dsInputSpecHandler =
                    (DSInputSpecParser) parse(dsInputSpecSource,
                                              new DSInputSpecParser(parentPID));
        }
        return dsInputSpecHandler.getServiceDSInputSpec();
    }

    private Mmap getMethodMap(InputSource methodMapSource)
            throws ObjectIntegrityException, RepositoryConfigurationException,
            GeneralException {
        if (methodMapHandler == null) {
            methodMapHandler =
                    (MmapParser) parse(methodMapSource,
                                       new MmapParser(parentPID));
        }
        return methodMapHandler.getMethodMap();
    }

    private Service getService(InputSource wsdlSource)
            throws ObjectIntegrityException, RepositoryConfigurationException,
            GeneralException {
        if (wsdlHandler == null) {
            wsdlHandler = (WSDLParser) parse(wsdlSource, new WSDLParser());
        }
        return wsdlHandler.getService();
    }

    private DefaultHandler parse(InputSource xml, DefaultHandler eventHandler)
            throws ObjectIntegrityException, RepositoryConfigurationException,
            GeneralException {
        try {
            // XMLSchema validation via SAX parser
            SAXParserFactory spf = SAXParserFactory.newInstance();
            spf.setNamespaceAware(true);
            spf.setValidating(false);
            SAXParser sp = spf.newSAXParser();
            DefaultHandler handler = eventHandler;
            XMLReader xmlreader = sp.getXMLReader();
            xmlreader.setContentHandler(handler);
            xmlreader.parse(xml);
            return handler;
        } catch (ParserConfigurationException e) {
            String msg =
                    "ServiceMapper returned parser error. "
                            + "The underlying exception was a "
                            + e.getClass().getName() + ".  "
                            + "The message was " + "\"" + e.getMessage() + "\"";
            throw new RepositoryConfigurationException(msg);
        } catch (SAXException e) {
            String msg =
                    "ServiceMapper returned SAXException. "
                            + "The underlying exception was a "
                            + e.getClass().getName() + ".  "
                            + "The message was " + "\"" + e.getMessage() + "\"";
            throw new ObjectIntegrityException(msg);
        } catch (Exception e) {
            String msg =
                    "ServiceMapper returned error. "
                            + "The underlying error was a "
                            + e.getClass().getName() + ".  "
                            + "The message was " + "\"" + e.getMessage() + "\"";
            e.printStackTrace();
            throw new GeneralException(msg);
        }
    }

    private MethodDefOperationBind[] merge(Service service, Mmap methodMap)
            throws ObjectIntegrityException, GeneralException {
        Port port = null;
        Binding binding = null;
        MethodDefOperationBind[] fedoraMethodDefBindings =
                new MethodDefOperationBind[0];

        // If the WSDL Service defines multiple Ports (with Binding) for the abstract operations
        // we must CHOOSE ONE binding for Fedora to work with.
        if (service.ports.length > 1) {
            port = choosePort(service);
        } else {
            port = service.ports[0];
        }

        binding = port.binding;

        // Reflect on the type of binding we are dealing with, then Fedora-ize things.
        if (binding.getClass().getName()
                .equalsIgnoreCase("org.fcrepo.server.storage.service.HTTPBinding")) {
            // Initialize the array to hold the Fedora-ized operation bindings.
            fedoraMethodDefBindings =
                    new MethodDefOperationBind[((HTTPBinding) binding).operations.length];

            for (int i = 0; i < ((HTTPBinding) binding).operations.length; i++) {
                // From methodMap which was previously created by parsing Fedora method map metadata
                // which provides a Fedora overlay on the service WSDL.
                MmapMethodDef methodDef =
                        (MmapMethodDef) methodMap.wsdlOperationToMethodDef
                                .get(((HTTPBinding) binding).operations[i].operationName);
                fedoraMethodDefBindings[i] = new MethodDefOperationBind();
                fedoraMethodDefBindings[i].methodName = methodDef.methodName;
                fedoraMethodDefBindings[i].methodLabel = methodDef.methodLabel;
                fedoraMethodDefBindings[i].methodParms = methodDef.methodParms;

                // From WSDL Port found in Service object
                fedoraMethodDefBindings[i].serviceBindingAddress =
                        port.portBaseURL;

                // From WSDL Binding found in Service object
                fedoraMethodDefBindings[i].protocolType =
                        MethodDefOperationBind.HTTP_MESSAGE_PROTOCOL;
                fedoraMethodDefBindings[i].operationLocation =
                        ((HTTPBinding) binding).operations[i].operationLocation;
                fedoraMethodDefBindings[i].operationURL =
                        fedoraMethodDefBindings[i].serviceBindingAddress
                                .concat(fedoraMethodDefBindings[i].operationLocation);

                // Get the list of datastream input binding keys that pertain to the particular
                // operation binding.  From the WSDL perspective, the datastream input keys
                // are WSDL message parts that, according the the Fedora Method Map, are
                // datastream inputs to the operation.

                MmapMethodParmDef[] parms = methodDef.wsdlMsgParts;
                Vector<String> tmp_dsInputKeys = new Vector<String>();
                for (MmapMethodParmDef element : parms) {
                    if (element.parmType
                            .equalsIgnoreCase(MethodParmDef.DATASTREAM_INPUT)) {
                        tmp_dsInputKeys.add(element.parmName);
                    }
                }
                fedoraMethodDefBindings[i].dsBindingKeys =
                        (String[]) tmp_dsInputKeys.toArray(new String[0]);

                // Set the outputMIMETypes from the operation's output binding, if any
                HTTPOperationInOut oBind =
                        ((HTTPBinding) binding).operations[i].outputBinding;
                if (oBind != null) {
                    Vector<String> tmp_outputMIMETypes = new Vector<String>();
                    for (MIMEContent element : oBind.ioMIMEContent) {
                        tmp_outputMIMETypes.add(element.mimeType);
                    }
                    fedoraMethodDefBindings[i].outputMIMETypes =
                            (String[]) tmp_outputMIMETypes
                                    .toArray(new String[0]);
                }

            }
        } else if (binding.getClass().getName()
                .equalsIgnoreCase("org.fcrepo.server.storage.service.SOAPBinding")) {
            // FIXIT!!  Implement this!
        }
        return fedoraMethodDefBindings;
    }

    private Port choosePort(Service service) {
        // If there is an HTTP binding, this will be preferred.
        for (Port element : service.ports) {
            Binding binding = element.binding;
            if (binding
                    .getClass()
                    .getName()
                    .equalsIgnoreCase("org.fcrepo.server.storage.service.HTTPBinding")) {
                return element;
            }
        }
        // Otherwise, just return the first port for binding
        return service.ports[0];
    }
}
TOP

Related Classes of org.fcrepo.server.storage.service.ServiceMapper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.