org.eurekastreams.server.service.opensocial.gadgets.spec.GadgetMetaDataHttpFetcher.java Source code

Java tutorial

Introduction

Here is the source code for org.eurekastreams.server.service.opensocial.gadgets.spec.GadgetMetaDataHttpFetcher.java

Source

/*
 * Copyright (c) 2009-2010 Lockheed Martin Corporation
 *
 * 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 org.eurekastreams.server.service.opensocial.gadgets.spec;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eurekastreams.server.domain.GeneralGadgetDefinition;
import org.eurekastreams.server.domain.gadgetspec.EnumValuePairDTO;
import org.eurekastreams.server.domain.gadgetspec.GadgetMetaDataDTO;
import org.eurekastreams.server.domain.gadgetspec.UserPrefDTO;
import org.eurekastreams.server.domain.gadgetspec.UserPrefDTO.DataType;

/**
 * This class provides the mechanism for retrieving the gadget metadata contained with gadget definitions that are
 * supplied.
 *
 */
public class GadgetMetaDataHttpFetcher implements GadgetMetaDataFetcher {
    /**
     * Base url for the Current App where the metadata request will be made to.
     */
    private String currentAppContextBaseUrl;

    /**
     * Constant byte size for characters.
     */
    private static final int CHAR_BYTE = 1024;

    /**
     * Local logging instance.
     */
    private final Log logger = LogFactory.getLog(GadgetMetaDataHttpFetcher.class);

    /**
     * Setter for the Current Application Context Base Url to be used for retrieving gadget metadata from the container.
     *
     * @param inCurrentAppContextBaseUrl
     *            - base url for the gadget metadata fetcher.
     */
    public void setCurrentAppContextBaseUrl(final String inCurrentAppContextBaseUrl) {
        currentAppContextBaseUrl = inCurrentAppContextBaseUrl;
    }

    /**
     * Retrieve the gadget metadata for the gadget definitions passed into the class.
     *
     * @param gadgetDefs
     *            Map of gadget definitions with the string key as the gadget def url.
     * @return List of GadgetMetaData objects that contain the metadata for the Gadget definitions passed in.
     * @throws Exception
     *             Error occurs on retrieving gadget metadata.
     */
    public List<GadgetMetaDataDTO> getGadgetsMetaData(final Map<String, GeneralGadgetDefinition> gadgetDefs)
            throws Exception {
        if (gadgetDefs.isEmpty()) {
            return Collections.EMPTY_LIST;
        }

        try {
            // Make the http request here.
            StringWriter output = new StringWriter();
            URL endpoint = new URL(currentAppContextBaseUrl + "/gadgets/metadata");
            logger.debug("Target url for metadata request " + endpoint.toString());
            HttpURLConnection urlConnection = null;
            try {
                // Open the HttpConnection and make the POST.
                urlConnection = (HttpURLConnection) endpoint.openConnection();
                urlConnection.setRequestMethod("POST");
                urlConnection.setDoInput(true);
                urlConnection.setDoOutput(true);
                urlConnection.setAllowUserInteraction(false);
                urlConnection.setRequestProperty("Content-type", "application/json");
                OutputStream out = urlConnection.getOutputStream();
                try {
                    Writer writer = new OutputStreamWriter(out, "UTF-8");
                    pipe(new StringReader(assembleMetaDataRequestContext(gadgetDefs)), writer);
                    writer.close();
                } catch (IOException e) {
                    String ioErrorMsg = "IOException occurred writing params to outputstream.";
                    logger.error(ioErrorMsg, e);
                    throw new Exception(ioErrorMsg);
                } finally {
                    if (out != null) {
                        out.close();
                    }
                }

                // Retrieve the response.
                InputStream in = urlConnection.getInputStream();
                try {
                    Reader reader = new InputStreamReader(in);
                    pipe(reader, output);
                    reader.close();
                } catch (IOException iox) {
                    String ioErrorMsg = "IOException occurred reading response from request";
                    logger.error(ioErrorMsg, iox);
                    throw iox;
                } finally {
                    if (in != null) {
                        in.close();
                    }
                }

                logger.debug("This is the output of the MetaData request: " + output.toString());
            } catch (IOException ioex) {
                throw ioex;
            } finally {
                if (urlConnection != null) {
                    urlConnection.disconnect();
                }
            }

            return mapGadgetMetaDataJSONToObject(output.toString(), gadgetDefs);
        } catch (Exception ex) {
            String msg = "Error occurred retrieving gadget metadata " + ex;
            logger.error(msg, ex);
            throw ex;
        }
    }

    /**
     * This method converts the MetaData JSON into a List of GadgetMetaData objects.
     *
     * @param inGadgetsJSON
     *            raw results from the metadata request.
     * @param gadgetDefs
     *            Map of gadget definitions with the string key as the gadget def url.
     * @return List of GadgetMetaData objects from the request.
     */
    private List<GadgetMetaDataDTO> mapGadgetMetaDataJSONToObject(final String inGadgetsJSON,
            final Map<String, GeneralGadgetDefinition> gadgetDefs) {
        List<GadgetMetaDataDTO> currentGadgetMetaData = new ArrayList<GadgetMetaDataDTO>();
        JSONObject gadgetsMetaData = JSONObject.fromObject(inGadgetsJSON.toString());
        JSONArray gadgetsJSON = gadgetsMetaData.getJSONArray("gadgets");
        GadgetMetaDataDTO currentGadget;

        for (int index = 0; index < gadgetsJSON.size(); index++) {
            JSONObject gadgetJSON = gadgetsJSON.getJSONObject(index);
            currentGadget = new GadgetMetaDataDTO(gadgetDefs.get(gadgetJSON.get("url")));
            // set the user prefs here as a list.
            currentGadget.setTitle(gadgetJSON.containsKey("title") ? gadgetJSON.getString("title") : "");
            currentGadget.setAuthor(gadgetJSON.containsKey("author") ? gadgetJSON.getString("author") : "");
            currentGadget.setDescription(
                    gadgetJSON.containsKey("description") ? gadgetJSON.getString("description") : "");
            JSONObject gadgetUserPrefsJSON = gadgetJSON.getJSONObject("userPrefs");
            List<UserPrefDTO> userPrefs = new ArrayList<UserPrefDTO>();
            UserPrefDTO currentUserPref;
            JSONObject currentUserPrefJSON;
            String currentUserPrefKey;
            for (Object userPrefKey : gadgetUserPrefsJSON.keySet()) {
                currentUserPrefKey = (String) userPrefKey;
                currentUserPrefJSON = gadgetUserPrefsJSON.getJSONObject(currentUserPrefKey);
                currentUserPref = new UserPrefDTO();
                currentUserPref.setName(currentUserPrefKey);
                currentUserPref.setDisplayName(currentUserPrefJSON.getString("displayName"));
                currentUserPref.setDataType(currentUserPrefJSON.getString("type"));
                currentUserPref.setDefaultValue(currentUserPrefJSON.getString("default"));
                if (currentUserPref.getDataType().name() == DataType.ENUM.name()) {
                    // Unordered easy access map of enum values.
                    Map<String, String> enumValues = new HashMap<String, String>();
                    String enumKey;
                    String userPrefEnumValue;
                    // parse enum values here
                    for (Object enumKeyObject : currentUserPrefJSON.getJSONObject("enumValues").keySet()) {
                        enumKey = (String) enumKeyObject;
                        userPrefEnumValue = (String) currentUserPrefJSON.getJSONObject("enumValues").get(enumKey);
                        enumValues.put(enumKey, userPrefEnumValue);
                    }
                    currentUserPref.setEnumValues(enumValues);

                    // Ordered enum values for creating preferences.
                    List<EnumValuePairDTO> orderedEnumValues = new LinkedList<EnumValuePairDTO>();
                    JSONArray orderedEnumValuesJson = currentUserPrefJSON.getJSONArray("orderedEnumValues");
                    JSONObject currentOrderedEnumValueJson;
                    for (int arrayIndex = 0; arrayIndex < orderedEnumValuesJson.size(); arrayIndex++) {
                        currentOrderedEnumValueJson = orderedEnumValuesJson.getJSONObject(arrayIndex);
                        orderedEnumValues.add(new EnumValuePairDTO(currentOrderedEnumValueJson.getString("value"),
                                currentOrderedEnumValueJson.getString("displayValue")));
                    }
                    currentUserPref.setOrderedEnumValues(orderedEnumValues);
                }

                if (currentUserPrefJSON.containsKey("required")) {
                    currentUserPref.setRequired(currentUserPrefJSON.getString("required"));
                }
                userPrefs.add(currentUserPref);
            }
            currentGadget.setUserPrefs(userPrefs);
            currentGadgetMetaData.add(currentGadget);
        }
        return currentGadgetMetaData;
    }

    /**
     * This method assembles the context for the metadata request to the OpenSocial container.
     *
     * @param gadgetDefs
     *            Map of gadget definitions with the string key as the gadget def url.
     * @return String representation of the JSON Context.
     */
    private String assembleMetaDataRequestContext(final Map<String, GeneralGadgetDefinition> gadgetDefs) {
        // Assemble the json for requesting the metadata for a gadget.
        JSONObject metaDataParams = new JSONObject();
        JSONObject contextParams = new JSONObject();
        contextParams.put("country", "default");
        contextParams.put("language", "default");
        contextParams.put("view", "preview");
        contextParams.put("container", "eureka");
        metaDataParams.put("context", contextParams);

        JSONArray gadgetParams = new JSONArray();
        JSONObject gadgetDefParam;
        for (Entry<String, GeneralGadgetDefinition> currentGadgetDef : gadgetDefs.entrySet()) {
            gadgetDefParam = new JSONObject();
            gadgetDefParam.put("url", currentGadgetDef.getKey());
            gadgetDefParam.put("moduleId", currentGadgetDef.getValue().getId());
            gadgetParams.add(gadgetDefParam);
        }
        metaDataParams.put("gadgets", gadgetParams);

        logger.debug("Created JSON for metadata request: " + metaDataParams.toString());

        return metaDataParams.toString();
    }

    /**
     * Helper method for copying a Reader into a writer.
     *
     * @param reader
     *            - containing the reader content to be written.
     * @param writer
     *            - target writer.
     * @throws IOException
     *             on stream errors.
     */
    private static void pipe(final Reader reader, final Writer writer) throws IOException {
        char[] buf = new char[CHAR_BYTE];
        int read = 0;
        while ((read = reader.read(buf)) >= 0) {
            writer.write(buf, 0, read);
        }
        writer.flush();
    }
}