org.easysoa.registry.dbb.rest.ServiceFinderRest.java Source code

Java tutorial

Introduction

Here is the source code for org.easysoa.registry.dbb.rest.ServiceFinderRest.java

Source

/**
 * EasySOA Registry
 * Copyright 2011 Open Wide
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Contact : easysoa-dev@googlegroups.com
 */

package org.easysoa.registry.dbb.rest;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;

import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.log4j.Logger;
import org.easysoa.registry.DocumentService;
import org.easysoa.registry.dbb.BrowsingContext;
import org.easysoa.registry.dbb.FoundService;
import org.easysoa.registry.dbb.ServiceFinderService;
import org.easysoa.registry.dbb.ServiceFinderStrategy;
import org.easysoa.registry.rest.EasysoaModuleRoot;
import org.easysoa.registry.types.Endpoint;
import org.json.JSONArray;
import org.json.JSONObject;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentModelList;
import org.nuxeo.ecm.webengine.jaxrs.session.SessionFactory;
import org.nuxeo.ecm.webengine.model.WebObject;
import org.nuxeo.runtime.api.Framework;

import com.sun.jersey.api.core.HttpContext;

/**
 * REST service to find WSDLs from given URL.
 * 
 * Use: .../nuxeo/site/easysoa/servicefinder/{url}
 * Params: {url} The URL of the page to consider (not encoded).
 * Other protocols than HTTP are not supported.
 * 
 * @author mkalam-alami
 * 
 */
@Path("easysoa/servicefinder")
//@Produces("application/x-javascript") // doesn't work for bookmarklet's jquery $.ajax() in jsonp ("parsing error")
@Produces("application/javascript") // required (?!) for bookmarklet's jquery $.ajax() in jsonp (else "parsing error")
@WebObject(type = "servicefinder")
public class ServiceFinderRest extends EasysoaModuleRoot {

    private static Logger logger = Logger.getLogger(ServiceFinderRest.class);

    private DocumentModelList endpointsCache = null;

    private List<String> environmentsNamesCache = null;

    @GET
    public Object getDefault() {
        return "Invalid use (please append an address to explore to the URL)";
    }

    /**
     * Computes a list of all existing environments, by analysing the endpoints properties.
     * @return
     * @throws Exception
     */
    @GET
    @Path("/environments")
    public Object getEnvironmentList() throws Exception {
        CoreSession session = SessionFactory.getSession(request);
        DocumentService docService = Framework.getService(DocumentService.class);
        DocumentModelList allEndpoints = docService.query(session, "SELECT * FROM " + Endpoint.DOCTYPE, true,
                false); // TODO Phase (LATER +component)

        // Use a cache for performance
        boolean computeEnvList = true;
        if (environmentsNamesCache != null) {
            if (endpointsCache != null && endpointsCache.equals(allEndpoints)) {
                computeEnvList = false;
            }
        }

        if (computeEnvList) {
            List<String> environmentsNames = new ArrayList<String>();
            for (DocumentModel endpoint : allEndpoints) {
                String environmentName = (String) endpoint.getPropertyValue(Endpoint.XPATH_ENDP_ENVIRONMENT);
                if (environmentName != null && !environmentsNames.contains(environmentName)) {
                    environmentsNames.add(environmentName);
                }
            }
            endpointsCache = allEndpoints;
            environmentsNamesCache = environmentsNames;
        }

        return new JSONArray(environmentsNamesCache).toString();
    }

    /**
     * JSONP for bookmarklet
     * NB. requires application/javascript mimetype to work on bookmarklet's
     * jquery $.ajax() side in jsonp, but doesn't work if set here, has to be put at the tope
     * @param uriInfo
     * @return
     * @throws Exception
     */
    @GET
    @Path("/find/{url:.*}")
    public Object findServices(@Context UriInfo uriInfo) throws Exception {

        URL url = null;
        String callback = null;
        try {
            // Retrieve URL
            String restServiceURL = uriInfo.getBaseUri().toString() + "easysoa/servicefinder/find/";
            url = new URL(uriInfo.getRequestUri().toString().substring(restServiceURL.length()));

            if (url.getQuery() != null && url.getQuery().contains("callback=")) {
                List<NameValuePair> queryTokens = URLEncodedUtils.parse(url.toURI(), "UTF-8");
                for (NameValuePair token : queryTokens) {
                    if (token.getName().equals("callback")) {
                        callback = token.getValue(); // now let's remove this callback from original jsonp URL
                    }
                }
            }
        } catch (MalformedURLException e) {
            logger.debug(e);
            return "{ errors: '" + formatError(e) + "' }";
        }

        // Find WSDLs
        String foundServicesJson = findServices(new BrowsingContext(url));
        String res;
        if (callback != null) {
            res = callback + '(' + foundServicesJson + ");"; // ')' // TODO OK
        } else {
            res = foundServicesJson;
        }
        return res;
    }

    @POST
    public Object findServices(@Context HttpContext httpContext, @Context HttpServletRequest request)
            throws Exception {

        // Retrieve params
        @SuppressWarnings("unchecked")
        Map<String, String> formValues = getFirstValues(request.getParameterMap());

        // Find WSDLs
        BrowsingContext browsingContext = new BrowsingContext(new URL(formValues.get("url")),
                formValues.get("data"));
        return findServices(browsingContext);
    }

    public String findServices(BrowsingContext context) throws Exception {

        JSONArray errors = new JSONArray();
        JSONObject result = new JSONObject();

        // Run finders
        List<FoundService> foundServices = new LinkedList<FoundService>();
        if (context.getURL() != null && context.getData() != null) {
            ServiceFinderService finderComponent = Framework.getService(ServiceFinderService.class);
            List<ServiceFinderStrategy> strategies = finderComponent.getStrategies();

            for (ServiceFinderStrategy strategy : strategies) {
                List<FoundService> strategyResult = null;
                try {
                    strategyResult = strategy.findFromContext(context);
                } catch (Exception e) {
                    errors.put(formatError(e,
                            "Failed to run service finder strategy " + strategy.getClass().getName()));
                }
                if (strategyResult != null) {
                    foundServices.addAll(strategyResult);
                }
            }
        }

        // TODO: Filter duplicates

        // Format response
        JSONObject foundLinks = new JSONObject();
        for (FoundService foundService : foundServices) {
            String appName = foundService.getApplicationName();
            if (appName != null) {
                result.put("applicationName", appName);
            }
            foundLinks.put(foundService.getName(), foundService.getURL());
        }
        if (foundLinks.keys().hasNext()) {
            result.put("foundLinks", foundLinks);
        }
        if (errors.length() > 0) {
            result.put("errors", errors);
        }

        return result.toString();

    }

    private static Map<String, String> getFirstValues(Map<String, String[]> multivaluedMap) {
        Map<String, String> map = new HashMap<String, String>();
        for (Entry<String, String[]> entry : multivaluedMap.entrySet()) {
            if (entry.getValue().length > 0) {
                map.put(entry.getKey(), entry.getValue()[0]);
            }
        }
        return map;
    }

    private String formatError(Exception e, String message) {
        return e.getClass().getSimpleName() + ": " + message + " (cause: " + e.getMessage() + ")";
    }

    private String formatError(Exception e) {
        return e.getClass().getSimpleName() + ": " + e.getMessage();
    }

}