All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.admingui.common.util.RestUtil Maven / Gradle / Ivy

There is a newer version: 7.2024.1.Alpha1
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2009-2019 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
// Portions Copyright [2017-2021] [Payara Foundation and/or its affiliates]

package org.glassfish.admingui.common.util;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.ClientRequestContext;
import jakarta.ws.rs.client.ClientRequestFilter;
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.Cookie;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;

import jakarta.faces.context.FacesContext;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import javax.xml.parsers.ParserConfigurationException;

import org.glassfish.jersey.client.filter.CsrfProtectionFilter;

import org.glassfish.hk2.api.ServiceLocator;

import org.glassfish.admingui.common.security.AdminConsoleAuthModule;
import org.glassfish.api.ActionReport.ExitCode;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.sun.enterprise.config.serverbeans.SecureAdmin;
import com.sun.enterprise.security.SecurityServicesUtil;
import com.sun.enterprise.security.ssl.SSLUtils;
import com.sun.jsftemplating.layout.descriptors.handler.HandlerContext;
import org.glassfish.jersey.jsonp.JsonProcessingFeature;

/**
 * Utilities for processing REST requests in the admin console
 * 
 * @author anilam
 */
public class RestUtil {

    public static final String FORM_ENCODING = "application/x-www-form-urlencoded";
    //default to .json instead of .xml
    public static final String RESPONSE_TYPE = "application/json";
    public static final String GUI_TOKEN_FOR_EMPTY_PROPERTY_VALUE = "()";
    public static final String REST_TOKEN_COOKIE = "gfresttoken";
    private static Client JERSEY_CLIENT;

    public static synchronized Client getJerseyClient() {
        if (JERSEY_CLIENT == null) {
            JERSEY_CLIENT = initialize(ClientBuilder.newBuilder()).build();
            JERSEY_CLIENT.register(new RequiredHeadersFilter())
                    .register(new JsonProcessingFeature());
        }

        return JERSEY_CLIENT;
    }

    public static String getPropValue(String endpoint, String propName, HandlerContext handlerCtx) {
        Map responseMap = restRequest(endpoint + "/property.json", null, "GET", handlerCtx, false);
        Map extraPropertiesMap = (Map) ((Map) responseMap.get("data")).get("extraProperties");
        if (extraPropertiesMap != null) {
            List> props = (List>) extraPropertiesMap.get("properties");
            for (Map oneProp : props) {
                if (oneProp.get("name").equals(propName)) {
                    return (String) oneProp.get("value");
                }
            }
        }
        return "";
    }

    public static String resolveToken(String endpoint, String token) {
        String tokenStartMarker = "${", tokenEndMarker = "}";

        if (!token.trim().startsWith(tokenStartMarker)) {
            return token;
        }
        int start = token.indexOf(tokenStartMarker);
        if (start < 0) {
            return token;
        }
        int end = token.lastIndexOf(tokenEndMarker);
        if (end < 0) {
            return token;
        }

        Map attrMap = new HashMap<>();
        String str = token.substring(start + tokenStartMarker.length(), end - tokenEndMarker.length() + 1);
        attrMap.put("tokens", str);

        try {
            Map result = restRequest(endpoint + "/resolve-tokens.json", attrMap, "GET", null, true);
            return (String) GuiUtil.getMapValue(result, "data,extraProperties,tokens," + str);
        } catch (Exception ex) {
            GuiUtil.getLogger().info(ex.getMessage());
        }
        return token;
    }

    public static Map restRequest(String endpoint, Map attrs, String method, HandlerContext handlerCtx, boolean quiet) {
        return restRequest(endpoint, attrs, method, handlerCtx, quiet, true);
    }

    public static Map restRequest(String endpoint, Map attrs, String method, HandlerContext handlerCtx, boolean quiet, boolean throwException) {
        boolean useData = false;

        Object data = null;
        if (attrs == null) {
            try {
                data = (handlerCtx == null) ? null : handlerCtx.getInputValue("data");
            } catch (Exception e) {
                //
            }
            if (data != null) {
                // We'll send the raw data
                useData = true;
            } else {
                // Initialize the attributes to an empty map
                attrs = new HashMap<>();
            }
        }
        method = method.toLowerCase(new Locale("UTF-8"));

        Logger logger = GuiUtil.getLogger();
        if (logger.isLoggable(Level.FINEST)) {
            Map maskedAttr = maskOffPassword(attrs);
            logger.log(Level.FINEST,
                       GuiUtil.getCommonMessage("LOG_REST_REQUEST_INFO",
                                                new Object[]{
                        endpoint,
                        (useData && "post".equals(method)) ? data : attrs, method
                    }));
        }

        // Execute the request...
        RestResponse restResponse = null;
        if ("post".equals(method)) {
            if (useData) {
                restResponse = post(endpoint, data, (String) handlerCtx.getInputValue("contentType"));
            } else {
                restResponse = post(endpoint, attrs);
            }
        } else if ("put".equals(method)) {
            if (useData) {
                restResponse = put(endpoint, data, (String) handlerCtx.getInputValue("contentType"));
            } else {
                restResponse = put(endpoint, attrs);
            }
        } else if ("get".equals(method)) {
            restResponse = get(endpoint, attrs);
        } else if ("delete".equals(method)) {
            restResponse = delete(endpoint, attrs);
        } else {
            throw new RuntimeException(GuiUtil.getCommonMessage("rest.invalid_method", new Object[]{method}));
        }

        // If the REST request returns a 401 (authz required), the REST "session"
        // has likely expired.  If the requested console URL is NOT the login page,
        // invalidate the session and force the the user to log back in.
        if (restResponse.getResponseCode() == 401) {
            FacesContext fc = FacesContext.getCurrentInstance();
            HttpSession session = (HttpSession) fc.getExternalContext().getSession(false);

            HttpServletRequest request = (HttpServletRequest) fc.getExternalContext().getRequest();
            HttpServletResponse response = (HttpServletResponse) fc.getExternalContext().getResponse();
            if (!"/login.jsf".equals(request.getServletPath())) {
                try {
                    response.sendRedirect("/");

                    fc.responseComplete();
                    session.invalidate();
                } catch (Exception ex) {
                    throw new RuntimeException(ex);
                }
            }
        }

        return parseResponse(restResponse, handlerCtx, endpoint, (useData && "post".equals(method)) ? data : attrs, quiet, throwException);
    }

//    public static  T restRequest(String endpoint,
//                                    Map attrs,
//                                    String method,
//                                    String contentType,
//                                    Object data,
//                                    boolean useData,
//                                    boolean quiet,
//                                    boolean throwException) {
//        method = method.toLowerCase(new Locale("UTF-8"));
//
//        Logger logger = GuiUtil.getLogger();
//        if (logger.isLoggable(Level.FINEST)) {
//            Map maskedAttr = maskOffPassword(attrs);
//            logger.log(Level.FINEST,
//                    GuiUtil.getCommonMessage("LOG_REST_REQUEST_INFO",
//                        new Object[]{
//                            endpoint,
//                            (useData && "post".equals(method))? data: attrs, method
//                        }));
//        }
//
//        // Execute the request...
//        RestResponse restResponse = null;
//        if ("post".equals(method)) {
//            if (useData) {
//                restResponse = post(endpoint, data, contentType);
//            } else {
//                restResponse = post(endpoint, attrs);
//            }
//        } else if ("put".equals(method)) {
//            restResponse = put(endpoint, attrs);
//        } else if ("get".equals(method)) {
//            restResponse = get(endpoint, attrs);
//        } else if ("delete".equals(method)) {
//            restResponse = delete(endpoint, attrs);
//        } else {
//            throw new RuntimeException(GuiUtil.getCommonMessage("rest.invalid_method", new Object[]{method}));
//        }
//
//        // If the REST request returns a 401 (authz required), the REST "session"
//        // has likely expired.  If the requested console URL is NOT the login page,
//        // invalidate the session and force the the user to log back in.
//        if (restResponse.getResponseCode() == 401) {
//            FacesContext fc = FacesContext.getCurrentInstance();
//            HttpSession session = (HttpSession)fc.getExternalContext().getSession(false);
//
//            HttpServletRequest request = (HttpServletRequest)fc.getExternalContext().getRequest();
//            HttpServletResponse response = (HttpServletResponse)fc.getExternalContext().getResponse();
//            if (!"/login.jsf".equals(request.getServletPath())) {
//                try {
//                    response.sendRedirect("/");
//
//                    fc.responseComplete();
//                    initialize(null);
//                    session.invalidate();
//                } catch (Exception ex) {
//                    throw new RuntimeException(ex);
//                }
//            }
//        }
//
//        return restResponse.;
//    }
    public static Map maskOffPassword(Map attrs) {
        Map masked = new HashMap<>();
        if (attrs == null) {
            return masked;
        }

        for (Map.Entry e : attrs.entrySet()) {
            String key = e.getKey().toLowerCase(GuiUtil.guiLocale);
            if (pswdAttrList.contains(key)) {
                masked.put(e.getKey(), "*******");
            } else {
                masked.put(e.getKey(), e.getValue());
            }
        }
        return masked;
    }

    public static Map buildDefaultValueMap(String endpoint) throws ParserConfigurationException, SAXException, IOException {
        Map defaultValues = new HashMap<>();

        RestResponse response = options(endpoint, "application/json");
        //System.out.println("=========== response.getResponse():\n " + response.getResponse());
        Map data = (Map) response.getResponse().get("data");
        List> methods = null;
        Map extraProperties = (Map) data.get("extraProperties");
        methods = (List>) extraProperties.get("methods");
        for (Map method : methods) {
            if ("POST".equals(method.get("name"))) {
                Map messageParameters = (Map) method.get("messageParameters");
                if (messageParameters != null) {
                    for (Map.Entry entry : messageParameters.entrySet()) {
                        String param = entry.getKey();
                        String defaultValue = (String) ((Map) entry.getValue()).get("defaultValue");
                        if (!"".equals(defaultValue) && (defaultValue != null)) { // null test necessary?
                            defaultValues.put(param, defaultValue);
                        }
                    }
                }
            }
        }
        return defaultValues;
    }

    public static Map getAttributesMap(String endpoint) {
        RestResponse response = null;
        try {
            response = get(endpoint);
            if (!response.isSuccess()) {
                return new HashMap<>();
            }
            return getEntityAttrs(endpoint, "entity");
        } finally {
            if (response != null) {
                response.close();
            }
        }
    }

    public static Map getEntityAttrs(String endpoint, String key) {
        Map valueMap = new HashMap<>();
        try {
            // Use restRequest to query the endpoint
            Map result = restRequest(endpoint, (Map) null, "get", null, false);
            int responseCode = (Integer) result.get("responseCode");
            if ((responseCode < 200) || (responseCode > 299)) {
                throw new RuntimeException((String) result.get("responseBody"));
            }

            // Pull off the attribute Map
            Map data = (Map) result.get("data");
            Map extraProperties = (Map) data.get("extraProperties");
            if (extraProperties.containsKey(key)) {
                valueMap = (Map) extraProperties.get(key);
            }
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }

        return valueMap;
    }

    private static String getMessage(Map aMap) {
        String message = "";
        if (aMap != null) {
            message = (String) aMap.get("message");
        }
        return (message == null) ? "" : message;
    }

    public static Map parseResponse(RestResponse response, HandlerContext handlerCtx, String endpoint,
                                                    Object attrs, boolean quiet, boolean throwException) {
        // Parse the response
        String message = "";
        ExitCode exitCode = ExitCode.FAILURE;
        Object maskedAttr = attrs;
        if ((attrs != null) && (attrs instanceof Map)) {
            maskedAttr = maskOffPassword((Map) attrs);
        }
        if (response != null) {
            try {
                //int status = response.getResponseCode();
                Map responseMap = response.getResponse();
                if (responseMap.get("data") != null) {
                    String exitCodeStr = (String) ((Map) responseMap.get("data")).get("exit_code");
                    exitCode = (exitCodeStr != null) ? ExitCode.valueOf(exitCodeStr) : ExitCode.SUCCESS;
                }

                //Get the message for both WARNING and FAILURE exit_code
                if (exitCode != ExitCode.SUCCESS) {
                    Map dataMap = (Map) responseMap.get("data");
                    if (dataMap != null) {
                        message = getMessage(dataMap);
                        List> subReports = (List>) dataMap.get("subReports");
                        if (subReports != null) {
                            StringBuilder sb = new StringBuilder("");
                            for (Map oneSubReport : subReports) {
                                sb.append(" ").append(getMessage(oneSubReport));
                            }
                            message = message + sb.toString();
                        }
                    } else {
                        Object msgs = responseMap.get("message");
                        if (msgs == null) {
                            //According to security guideline, we shouldn't expose the endpoint to user for the error.
                            //message =  "REST Request '"  + endpoint + "' failed with response code '" + status + "'.";
                            message = "";
                        } else if (msgs instanceof List) {
                            StringBuilder builder = new StringBuilder("");
                            for (Object obj : ((List) msgs)) {
                                if ((obj instanceof Map) && ((Map) obj).containsKey("message")) {
                                    obj = ((Map) obj).get("message");
                                }
                                builder.append(obj.toString());
                            }
                            message = builder.toString();
                        } else if (msgs instanceof Map) {
                            message = ((Map) msgs).get("message").toString();
                        } else {
                            throw new RuntimeException("Unexpected message type.");
                        }
                    }
                }
                switch (exitCode) {
                    case FAILURE: {
                        // If this is called from jsf, stop processing/show error.
                        if (throwException) {
                            if (handlerCtx != null) {
                                GuiUtil.handleError(handlerCtx, message);
                                if (!quiet) {
				    Logger logger = GuiUtil.getLogger();
                                    logger.severe(GuiUtil.getCommonMessage("LOG_REQUEST_RESULT", new Object[]{exitCode, endpoint, maskedAttr}));
				    if (logger.isLoggable(Level.FINEST)){
                                    	logger.finest("response.getResponseBody(): " + response.getResponseBody());
				    }
                                }
                                return new HashMap();
                            } else {
                                //If handlerCtx is not passed in, it means the caller (java handler) wants to handle this exception itself.
                                throw new RuntimeException(message);
                            }
                        } else { // Issue Number :13312 handling the case when throwException is false.
                            if (!quiet) {
				Logger logger = GuiUtil.getLogger();
                                logger.severe(GuiUtil.getCommonMessage("LOG_REQUEST_RESULT", new Object[]{exitCode, endpoint, maskedAttr}));
				if (logger.isLoggable(Level.FINEST)){
                                	logger.finest("response.getResponseBody(): " + response.getResponseBody());
				}
                            }
                            return responseMap;
                        }
                    }
                    case WARNING: {
                        GuiUtil.prepareAlert("warning", GuiUtil.getCommonMessage("msg.command.warning"), message);
                        GuiUtil.getLogger().warning(GuiUtil.getCommonMessage("LOG_REQUEST_RESULT", new Object[]{exitCode, endpoint, maskedAttr}));
                        return responseMap;
                    }
                    case SUCCESS: {
                        return responseMap;
                    }
                }
            } catch (Exception ex) {
                if (!quiet) {
		    Logger logger = GuiUtil.getLogger();
                    logger.severe(GuiUtil.getCommonMessage("LOG_REQUEST_RESULT", new Object[]{exitCode, endpoint, maskedAttr}));
		    if (logger.isLoggable(Level.FINEST)){
                        logger.log(Level.FINEST, "response.getResponseBody(): {0}", response.getResponseBody());
		    }
                }
                if (handlerCtx != null) {
                    //If this is called from the jsf as handler, we want to stop processing and show error
                    //instead of dumping the exception on screen.
                    if (throwException) {
                        if ("".equals(message)) {
                            GuiUtil.handleException(handlerCtx, ex);
                        } else {
                            GuiUtil.handleError(handlerCtx, message);
                        }
                    }
                } else {
                    //if this is called by other java handler, we tell the called handle the exception.
                    if ("".equals(message)) {
                        throw new RuntimeException(ex);
                    } else {
                        throw new RuntimeException(message, ex);
                    }
                }
            }
        }
        return null;
    }

    public static boolean hasWarning(Map responseMap) {
        if (responseMap.get("data") != null) {
            String exitCodeStr = (String) ((Map) responseMap.get("data")).get("exit_code");
            ExitCode exitCode = (exitCodeStr != null) ? ExitCode.valueOf(exitCodeStr) : ExitCode.SUCCESS;
            return (exitCode == ExitCode.WARNING);
        }
        return false;
    }

    /**
     * This method will encode append segment to base, encoding it so that a correct URL is returned.
     *
     * @param base
     * @param segment
     * @return
     */
    public static String appendEncodedSegment(String base, String segment) {
        String encodedUrl = getJerseyClient().target(base).getUriBuilder().segment(segment).build().toASCIIString();
        //segment(elementName)

        return encodedUrl;
    }

    //*******************************************************************************************************************
    //*******************************************************************************************************************
    protected static MultivaluedMap buildMultivalueMap(Map payload) {
        MultivaluedMap formData = new MultivaluedHashMap<>();
        if (payload == null || payload.isEmpty()) {
            return formData;
        }

        for (final Map.Entry entry : payload.entrySet()) {
            final Object value = entry.getValue();
            final String key = entry.getKey();
            if (value instanceof Collection) {
                for (Object obj : ((Collection) value)) {
                    try {
                        formData.add(key, obj);
                    } catch (ClassCastException ex) {
                        Logger logger = GuiUtil.getLogger();
                        if (logger.isLoggable(Level.FINEST)) {
                            logger.log(Level.FINEST,
                                       GuiUtil.getCommonMessage("LOG_BUILD_MULTI_VALUE_MAP_ERROR", new Object[]{key, obj}));
                        }

                        // Allow it to continue b/c this property most likely
                        // should have been excluded for this request
                    }
                }
            } else {
                //formData.putSingle(key, (value != null) ? value.toString() : value);
                try {
                    if (key.equals("availabilityEnabled")) {
                        System.out.println("================== availabilityEnabled  skipped ");
                    }
                    formData.putSingle(key, value);
                } catch (ClassCastException ex) {
                    Logger logger = GuiUtil.getLogger();
                    if (logger.isLoggable(Level.FINEST)) {
                        logger.log(Level.FINEST,
                                   GuiUtil.getCommonMessage("LOG_BUILD_MULTI_VALUE_MAP_ERROR", new Object[]{key, value}));
                    }
                    // Allow it to continue b/c this property most likely
                    // should have been excluded for this request
                }
            }
        }
        return formData;
    }

    public static RestResponse sendCreateRequest(String endpoint, Map attrs, List skipAttrs, List onlyUseAttrs, List convertToFalse) {
        removeSpecifiedAttrs(attrs, skipAttrs);
        attrs = buildUseOnlyAttrMap(attrs, onlyUseAttrs);
        attrs = convertNullValuesToFalse(attrs, convertToFalse);
        attrs = fixKeyNames(attrs);

        return post(endpoint, attrs);
    }

    // This will send an update request.  Currently, this calls post just like the create does,
    // but the REST API will be modified to use PUT for updates, a more correct use of HTTP
    public static RestResponse sendUpdateRequest(String endpoint, Map attrs, List skipAttrs, List onlyUseAttrs, List convertToFalse) {
        removeSpecifiedAttrs(attrs, skipAttrs);
        attrs = buildUseOnlyAttrMap(attrs, onlyUseAttrs);
        attrs = convertNullValuesToFalse(attrs, convertToFalse);
        attrs = fixKeyNames(attrs);

        return post(endpoint, attrs);
    }

    protected static Map fixKeyNames(Map map) {
        Map results = new HashMap<>();
        for (Map.Entry entry : map.entrySet()) {
            String key = entry.getKey().substring(0, 1).toLowerCase(GuiUtil.guiLocale) + entry.getKey().substring(1);
            Object value = entry.getValue();
            results.put(key, value);
        }

        return results;
    }

    protected static void removeSpecifiedAttrs(Map attrs, List removeList) {
        if (removeList == null || removeList.size() <= 0) {
            return;
        }
        Set> attrSet = attrs.entrySet();
        Iterator> iter = attrSet.iterator();
        while (iter.hasNext()) {
            Map.Entry oneEntry = iter.next();
            if (removeList.contains(oneEntry.getKey())) {
                iter.remove();
            }
        }
    }

    protected static Map buildUseOnlyAttrMap(Map attrs, List onlyUseAttrs) {
        if (onlyUseAttrs != null) {
            Map newAttrs = new HashMap<>();
            for (String key : onlyUseAttrs) {
                if (attrs.keySet().contains(key)) {
                    newAttrs.put(key, attrs.get(key));
                }
            }
            return newAttrs;
        } else {
            return attrs;
        }

    }

    // This is ugly, but I'm trying to figure out why the cleaner code doesn't work :(
    protected static Map convertNullValuesToFalse(Map attrs, List convertToFalse) {
        if (convertToFalse != null) {
            Map newAttrs = new HashMap<>();
            String key;

            for (Map.Entry entry : attrs.entrySet()) {
                key = entry.getKey();
                if (convertToFalse.contains(key) && ((entry.getValue() == null) || "null".equals(entry.getValue()))) {
                    newAttrs.put(key, "false");
                } else {
                    newAttrs.put(key, entry.getValue());
                }
            }
            return newAttrs;
        } else {
            return attrs;
        }
    }

    /**
     * Converts the first letter of the given string to Uppercase.
     *
     * @param string the input string
     * @return the string with the Uppercase first letter
     */
    public static String upperCaseFirstLetter(String string) {
        if (string == null || string.length() <= 0) {
            return string;
        }
        return string.substring(0, 1).toUpperCase(new Locale("UTF-8")) + string.substring(1);
    }

    public static List getChildResourceList(String document) throws SAXException, IOException, ParserConfigurationException {
        List children = new ArrayList<>();
        Document doc = MiscUtil.getDocument(document);
        Element root = doc.getDocumentElement();
        NodeList nl = root.getElementsByTagName("childResource");
        if (nl.getLength() > 0) {
            for (int i = 0; i < nl.getLength(); i++) {
                Node child = nl.item(i);
                if (child.getNodeType() == Node.ELEMENT_NODE) {
                    children.add(child.getTextContent());
                }
            }
        }

        return children;
    }

    /**
     * Given the parent URL and the desired childType, this method will build a List of Maps that contains each child
     * entities values. In addition to the entity values, each row will have a field, 'selected', set to false, as well
     * as the URL encoded entity name ('encodedName').
     *
     * @param parent
     * @param childType
     * @param skipList
     * @return
     * @throws Exception
     */
    public static List> buildChildEntityList(String parent, String childType, List skipList, List includeList, String id) throws Exception {

        String endpoint = parent.endsWith("/") ? parent + childType : parent + "/" + childType;
        boolean hasSkip = (skipList != null);
        boolean hasInclude = (includeList != null);
        boolean convert = childType.equals("property");

        List> childElements = new ArrayList<>();
        try {
            List childUrls = getChildList(endpoint);
            for (String childUrl : childUrls) {
                Map entity = getEntityAttrs(childUrl, "entity");
                HashMap oneRow = new HashMap<>();

                if (hasSkip && skipList.contains(entity.get(id))) {
                    continue;
                }

                if (hasInclude && (!includeList.contains(entity.get(id)))) {
                    continue;
                }

                oneRow.put("selected", false);
                for (Map.Entry e : entity.entrySet()) {
                    oneRow.put(e.getKey(), getA(entity, e.getKey(), convert));
                }
                oneRow.put("encodedName", URLEncoder.encode(entity.get(id).toString(), "UTF-8"));
                oneRow.put("name", entity.get(id));
                childElements.add(oneRow);
            }
        } catch (Exception e) {
            throw e;
        }
        return childElements;
    }

    private static String getA(Map attrs, String key, boolean convert) {
        Object val = attrs.get(key);
        if (val == null) {
            return "";
        }
        return (convert && (val.equals(""))) ? GUI_TOKEN_FOR_EMPTY_PROPERTY_VALUE : val.toString();
    }

    /**
     * Given the parent URL and the desired childType, this method will build a List of Strings that contains child
     * entity names.
     *
     * @param endpoint
     * @return
     * @throws Exception
     */
    public static List getChildList(String endpoint) throws Exception {
        List childElements = new ArrayList<>();
        Map childResources = getChildMap(endpoint);
        childElements.addAll(childResources.values());
        Collections.sort(childElements);
        return childElements;
    }

    public static Map getChildMap(String endpoint) throws Exception {
        return getChildMap(endpoint, null);
    }


    public static Map getChildMap(String endpoint, Map attrs) throws Exception {
        Map childElements = new TreeMap<>();
        if (attrs == null){
            attrs = new HashMap<>();
        }
        if (doesProxyExist(endpoint)) {
            Map responseMap = restRequest(endpoint, attrs, "get", null, false);
            Map data = (Map) responseMap.get("data");
            if (data != null) {
                Map extraProperties = (Map) data.get("extraProperties");
                if (extraProperties != null) {
                    childElements = (Map) extraProperties.get("childResources");
                    if (childElements == null) {
                        childElements = new TreeMap<>();
                    }
                }
            }
        }

        return childElements;
    }

    public static Boolean doesProxyExist(String endpoint) {
        RestResponse response = null;
        try {
            response = RestUtil.get(endpoint);
            if (response.isSuccess()) {
                return true;
            }
        } catch (Exception e) {
            return false;
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return false;
    }

    /**
     * 

This method returns the value of the REST token if it is successfully set in session scope.

* @return */ public static String getRestToken() { String token = null; FacesContext ctx = FacesContext.getCurrentInstance(); if (ctx != null) { token = (String) ctx.getExternalContext().getSessionMap(). get(AdminConsoleAuthModule.REST_TOKEN); } return token; } public static Response getRequestFromServlet(HttpServletRequest request, String endpoint, Map attrs) { String token = (String) request.getSession().getAttribute(AdminConsoleAuthModule.REST_TOKEN); WebTarget target = targetWithQueryParams(JERSEY_CLIENT.target(endpoint), attrs); Response cr = target .request().cookie(new Cookie(REST_TOKEN_COOKIE, token)) .get(Response.class); return cr; } public static void getRestRequestFromServlet(HttpServletRequest request, String endpoint, Map attrs, boolean quiet, boolean throwException) { String token = (String) request.getSession().getAttribute(AdminConsoleAuthModule.REST_TOKEN); WebTarget target = targetWithQueryParams(JERSEY_CLIENT.target(endpoint), attrs); Response cr = target .request(RESPONSE_TYPE) .cookie(new Cookie(REST_TOKEN_COOKIE, token)) .get(Response.class); RestResponse rr = RestResponse.getRestResponse(cr); parseResponse(rr, null, endpoint, attrs, quiet, throwException); } public static WebTarget targetWithQueryParams(WebTarget target, Map paramMap) { for (Map.Entry param : paramMap.entrySet()) { target = target.queryParam(param.getKey(), param.getValue()); } return target; } //****************************************************************************************************************** // Jersey client methods //****************************************************************************************************************** public static RestResponse get(String address) { return get(address, new HashMap()); } public static RestResponse get(String address, Map payload) { if (address.startsWith("/")) { address = FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("REST_URL") + address; } WebTarget target = targetWithQueryParams(getJerseyClient().target(address), payload); Response resp = target .request(RESPONSE_TYPE) .cookie(new Cookie(REST_TOKEN_COOKIE, getRestToken())) .get(Response.class); return RestResponse.getRestResponse(resp); } public static RestResponse post(String address, Object payload, String contentType) { WebTarget target = getJerseyClient().target(address); if (contentType == null) { contentType = MediaType.APPLICATION_JSON; } if (payload instanceof Map) { payload = buildMultivalueMap((Map) payload); } Response cr = target.request(RESPONSE_TYPE).header("Content-Type", contentType) .cookie(new Cookie(REST_TOKEN_COOKIE, getRestToken())) // .header("Content-type", MediaType.APPLICATION_FORM_URLENCODED) .post(Entity.entity(payload, contentType), Response.class); RestResponse rr = RestResponse.getRestResponse(cr); return rr; } public static RestResponse post(String address, Map payload) { WebTarget target = getJerseyClient().target(address); Response cr = target .request(RESPONSE_TYPE) .cookie(new Cookie(REST_TOKEN_COOKIE, getRestToken())) .post(getEntityForAddress(address, payload), Response.class); RestResponse rr = RestResponse.getRestResponse(cr); return rr; } private static Entity getEntityForAddress(String address, Map payload) { return address.endsWith("system-properties") ? Entity.entity(payload, MediaType.APPLICATION_JSON) : Entity.entity(buildMultivalueMap(payload), MediaType.APPLICATION_FORM_URLENCODED); } public static RestResponse put(String address, Object payload, String contentType) { WebTarget target = getJerseyClient().target(address); if (contentType == null) { contentType = MediaType.APPLICATION_JSON; } if (payload instanceof Map) { payload = buildMultivalueMap((Map) payload); } Response cr = target.request(RESPONSE_TYPE).header("Content-Type", contentType) .cookie(new Cookie(REST_TOKEN_COOKIE, getRestToken())) // .header("Content-type", MediaType.APPLICATION_FORM_URLENCODED) .put(Entity.entity(payload, contentType), Response.class); RestResponse rr = RestResponse.getRestResponse(cr); return rr; } public static RestResponse put(String address, Map payload) { WebTarget target = getJerseyClient().target(address); MultivaluedMap formData = buildMultivalueMap(payload); Response cr = target // .header("Content-type", MediaType.APPLICATION_FORM_URLENCODED) .request(RESPONSE_TYPE) .cookie(new Cookie(REST_TOKEN_COOKIE, getRestToken())) .put(Entity.entity(formData, MediaType.APPLICATION_FORM_URLENCODED), Response.class); RestResponse rr = RestResponse.getRestResponse(cr); return rr; } public static RestResponse delete(String address, Map payload) { WebTarget target = getJerseyClient().target(address); Response cr = targetWithQueryParams(target, payload) .request(RESPONSE_TYPE) .cookie(new Cookie(REST_TOKEN_COOKIE, getRestToken())) .delete(Response.class); return RestResponse.getRestResponse(cr); } public static RestResponse options(String address, String responseType) { WebTarget target = getJerseyClient().target(address); Response cr = target .request(responseType) .cookie(new Cookie(REST_TOKEN_COOKIE, getRestToken())) .options(Response.class); return RestResponse.getRestResponse(cr); } public static void checkStatusForSuccess(Response cr) { int status = cr.getStatus(); if ((status < 200) || (status > 299)) { throw new RuntimeException(cr.toString()); } } //****************************************************************************************************************** // Jersey client methods //****************************************************************************************************************** public static ClientBuilder initialize(ClientBuilder clientBuilder) { try { ServiceLocator habitat = SecurityServicesUtil.getInstance().getHabitat(); SecureAdmin secureAdmin = habitat.getService(SecureAdmin.class); final SSLContext sslContext = habitat .getService(SSLUtils.class) .getAdminSSLContext(SecureAdmin.Util.DASAlias(secureAdmin), null); // Instruct Jersey to use HostNameVerifier and SSLContext provided by us. clientBuilder .hostnameVerifier(new BasicHostnameVerifier()) .sslContext(sslContext) .register(CsrfProtectionFilter.class); } catch (Exception ex) { GuiUtil.getLogger().warning("RestUtil.initialize() failed"); if (GuiUtil.getLogger().isLoggable(Level.FINE)) { ex.printStackTrace(); } } return clientBuilder; } public static void postRestRequestFromServlet(HttpServletRequest request, String endpoint, Map attrs, boolean quiet, boolean throwException) { String token = (String) request.getSession().getAttribute(AdminConsoleAuthModule.REST_TOKEN); WebTarget target = JERSEY_CLIENT.target(endpoint); MultivaluedMap formData = buildMultivalueMap(attrs); Response cr = target .request(RESPONSE_TYPE) .cookie(new Cookie(REST_TOKEN_COOKIE, token)) .post(Entity.entity(formData, MediaType.APPLICATION_FORM_URLENCODED), Response.class); RestResponse rr = RestResponse.getRestResponse(cr); parseResponse(rr, null, endpoint, attrs, quiet, throwException); } private static class RequiredHeadersFilter implements ClientRequestFilter { @Override public void filter(ClientRequestContext requestContext) throws IOException { requestContext.getHeaders().add("X-GlassFish-3", "true"); } } private static class BasicHostnameVerifier implements HostnameVerifier { final HostnameVerifier defaultVerifier = javax.net.ssl.HttpsURLConnection.getDefaultHostnameVerifier(); public BasicHostnameVerifier() { } @Override public boolean verify(String host, SSLSession sslSession) { if (host.equals("localhost")) { return true; } boolean result = defaultVerifier.verify(host, sslSession); return (result) ? true : host.equals(sslSession.getPeerHost()); } } /* This is a list of attribute name of password for different command. * We need to mask its value during logging. */ private static final List pswdAttrList = Arrays.asList( "sshpassword", /* create-node-ssh , setup-ssh , update-node, update-node-ssh */ "windowspassword", /* create-node-dcom, validate-dcom, update-node-dcom, */ "dbpassword", /* jms-availability-service */ "jmsdbpassword", /* configure-jms-cluster */ "password", /* change-admin-password */ "newpassword", /* change-admin-password */ "jmsdbpassword", /* configure-jms-cluster */ "mappedpassword", /* create-connector-security-map, update-connector-security-map */ "userpassword", /* create-file-user , update-file-user */ "aliaspassword" /* create-password-alias , update-password-alias */); }