edu.unc.lib.dl.fedora.AccessClient.java Source code

Java tutorial

Introduction

Here is the source code for edu.unc.lib.dl.fedora.AccessClient.java

Source

/**
 * Copyright 2008 The University of North Carolina at Chapel Hill
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package edu.unc.lib.dl.fedora;

import static edu.unc.lib.dl.fedora.AuthorizationException.AuthorizationErrorType.INDETERMINATE;
import static edu.unc.lib.dl.fedora.AuthorizationException.AuthorizationErrorType.NOT_APPLICABLE;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.client.WebServiceFaultException;
import org.springframework.ws.client.WebServiceIOException;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.client.SoapFaultClientException;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
import org.springframework.ws.transport.http.CommonsHttpMessageSender;

import edu.unc.lib.dl.fedora.types.ArrayOfString;
import edu.unc.lib.dl.fedora.types.DescribeRepository;
import edu.unc.lib.dl.fedora.types.DescribeRepositoryResponse;
import edu.unc.lib.dl.fedora.types.FieldSearchQuery;
import edu.unc.lib.dl.fedora.types.FindObjects;
import edu.unc.lib.dl.fedora.types.FindObjectsResponse;
import edu.unc.lib.dl.fedora.types.GetDatastreamDissemination;
import edu.unc.lib.dl.fedora.types.GetDatastreamDisseminationResponse;
import edu.unc.lib.dl.fedora.types.GetObjectProfile;
import edu.unc.lib.dl.fedora.types.GetObjectProfileResponse;
import edu.unc.lib.dl.fedora.types.MIMETypedStream;
import edu.unc.lib.dl.fedora.types.ObjectFields;
import edu.unc.lib.dl.fedora.types.ObjectProfile;

/**
 * The AccessClient is a Fedora 3.0 API-A SOAP client bean. After the fedoraUrl, username and password properties are
 * set, call the init() method before using it.
 * <p>
 * For Fedora 3.0 API documentation, please consult the <a
 * href="https://fedora-commons.org/confluence/display/FCR30/API-A">wiki</a>.
 * </p>
 *
 * @author count0
 *
 */
public class AccessClient extends WebServiceTemplate {
    /**
     * These are the actions support by the Fedora API-A service.
     *
     * @author count0
     *
     */
    private enum Action {
        describeRepository("describeRepository"), findObjects("findObjects"), getDatastreamDissemination(
                "getDatastreamDissemination"), getObjectProfile("getObjectProfile");
        String uri = null;

        Action(String action) {
            uri = "http://www.fedora.info/definitions/1/0/api/#" + action;
        }

        WebServiceMessageCallback callback() {
            return new WebServiceMessageCallback() {
                @Override
                public void doWithMessage(WebServiceMessage message) {
                    ((SoapMessage) message).setSoapAction(uri);
                }
            };
        }
    }

    private static final Log log = LogFactory.getLog(AccessClient.class);
    private String fedoraContextUrl;
    private String password;
    private String username;

    /**
     * Encapsulates all marshalled web service calls.
     *
     * @param request
     *           a marshalled request object
     * @param action
     *           the Fedora API-A action
     * @return an unmarshalled response object
     */
    private Object callService(Object request, Action action) throws FedoraException {
        return callService(request, action, true);
    }

    private Object callService(Object request, Action action, boolean retry) throws FedoraException {
        Object response = null;
        try {
            response = this.marshalSendAndReceive(request, action.callback());
        } catch (WebServiceIOException e) {
            if (e.getMessage().contains("503")) {
                throw new FedoraTimeoutException(e);
            } else if (java.net.SocketTimeoutException.class.isInstance(e.getCause())) {
                throw new FedoraTimeoutException(e);
            } else {
                throw new ServiceException(e);
            }
        } catch (SoapFaultClientException e) {
            try {
                FedoraFaultMessageResolver.resolveFault(e);
            } catch (AuthorizationException ae) {
                if (retry && (NOT_APPLICABLE.equals(ae.getType()) || INDETERMINATE.equals(ae.getType()))) {
                    log.warn("Authorization failed, attempting to reestablish connection to Fedora.");
                    try {
                        this.init();
                    } catch (Exception e1) {
                        log.error("Failed to reestablish connection to Fedora", e);
                        throw ae;
                    }
                    return callService(request, action, false);
                }

                throw ae;
            }
        } catch (WebServiceFaultException e) {
            throw new ServiceException(e);
        }
        return response;
    }

    public DescribeRepositoryResponse describeRepository(DescribeRepository o)
            throws ServiceException, FedoraException {
        DescribeRepositoryResponse response = (DescribeRepositoryResponse) this.callService(o,
                Action.describeRepository);
        return response;
    }

    public List<PID> findAllObjectPIDs() throws FedoraException, ServiceException {
        List<PID> result = new ArrayList<PID>();
        FindObjects fo = new FindObjects();
        fo.setMaxResults(BigInteger.valueOf(100000));
        FieldSearchQuery query = new FieldSearchQuery();
        fo.setQuery(query);
        ArrayOfString fields = new ArrayOfString();
        fields.getItem().add("pid");
        fo.setResultFields(fields);
        FindObjectsResponse response = (FindObjectsResponse) this.callService(fo, Action.findObjects);
        for (ObjectFields o : response.getResult().getResultList().getObjectFields()) {
            String s = o.getPid().getValue();
            result.add(new PID(s));
        }
        return result;
    }

    public MIMETypedStream getDatastreamDissemination(PID pid, String dsid, String timestamp)
            throws FedoraException, ServiceException {
        GetDatastreamDissemination req = new GetDatastreamDissemination();
        req.setPid(pid.getPid());
        // TODO: test that NotFoundException is throw for non-existant datastreams
        req.setDsID(dsid);
        if (timestamp != null) {
            req.setAsOfDateTime(timestamp);
        }
        GetDatastreamDisseminationResponse response = (GetDatastreamDisseminationResponse) this.callService(req,
                Action.getDatastreamDissemination);
        return response.getDissemination();
    }

    public ObjectProfile getObjectProfile(PID pid, String timestamp) throws FedoraException, ServiceException {
        GetObjectProfile req = new GetObjectProfile();
        req.setPid(pid.getPid());
        if (timestamp != null) {
            req.setAsOfDateTime(timestamp);
        }
        GetObjectProfileResponse response = (GetObjectProfileResponse) this.callService(req,
                Action.getObjectProfile);
        return response.getObjectProfile();
    }

    /**
     * Get the Fedora base URL.
     *
     * @return Fedora base URL
     */
    public String getFedoraContextUrl() {
        return fedoraContextUrl;
    }

    /**
     * Get the Fedora password.
     *
     * @return
     */
    public String getPassword() {
        return password;
    }

    /**
     * Get the Fedora username
     *
     * @return
     */
    public String getUsername() {
        return username;
    }

    /**
     * Initializes this client bean, calling the initializers of dependencies.
     *
     * @throws Exception
     *            when initialization fails
     */
    public void init() throws Exception {
        SaajSoapMessageFactory msgFactory = new SaajSoapMessageFactory();
        msgFactory.afterPropertiesSet();
        this.setMessageFactory(msgFactory);

        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        marshaller.setContextPath("edu.unc.lib.dl.fedora.types");
        marshaller.afterPropertiesSet();
        this.setMarshaller(marshaller);
        this.setUnmarshaller(marshaller);

        CommonsHttpMessageSender messageSender = new CommonsHttpMessageSender();
        UsernamePasswordCredentials creds = new UsernamePasswordCredentials(this.username, this.password);
        messageSender.setCredentials(creds);
        messageSender.afterPropertiesSet();
        this.setMessageSender(messageSender);

        // this.setFaultMessageResolver(new FedoraFaultMessageResolver());
        this.setDefaultUri(this.getFedoraContextUrl() + "/services/access");
        this.afterPropertiesSet();
    }

    /**
     * Set the Fedora base URL.
     *
     * @param fedoraUrl
     */
    public void setFedoraContextUrl(String fedoraContextUrl) {
        this.fedoraContextUrl = fedoraContextUrl;
    }

    /**
     * Set the Fedora password.
     *
     * @param password
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * Set the Fedora username
     *
     * @param username
     */
    public void setUsername(String username) {
        this.username = username;
    }
}