org.openiot.ide.core.MenuFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.openiot.ide.core.MenuFactory.java

Source

package org.openiot.ide.core;

/**
 *    Copyright (c) 2011-2014, OpenIoT
 *
 *    This file is part of OpenIoT.
 *
 *    OpenIoT 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, version 3 of the License.
 *
 *    OpenIoT 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 OpenIoT.  If not, see <http://www.gnu.org/licenses/>.
 *
 *     Contact: OpenIoT mailto: info@openiot.eu
 */

import org.apache.commons.collections.map.MultiValueMap;
import org.apache.commons.lang3.StringUtils;
import org.omnifaces.util.Faces;
import org.openiot.commons.util.PropertyManagement;
import org.primefaces.model.menu.DefaultMenuItem;
import org.primefaces.model.menu.DefaultMenuModel;
import org.primefaces.model.menu.DefaultSubMenu;

import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;

import java.io.IOException;
import java.io.Serializable;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Chris Georgoulis e-mail: cgeo@ait.edu.gr
 */
@RequestScoped
public class MenuFactory implements Serializable {

    private static final String IDE_CORE_GROUP = "ide.core.navigation.";
    private static final String IDE_CORE_RELATIVE_URL = "ide.core";

    private static final String FIELD_TITLE = "title";
    private static final String FIELD_MONITORING = "monitoring";
    private static final String FIELD_URL = "url";

    private static final String IDE_CORE_MONITORING_URL = Faces.getRequestDomainURL() + "/" + IDE_CORE_RELATIVE_URL
            + "/" + FIELD_MONITORING;

    private static final String SUBMENU_MAIN = "Main Menu";
    private static final String SUBMENU_MONITORS = "Monitors";

    private static final String MENU_ICON = "ui-icon-triangle-1-e";
    private static final String CENTER_PANEL = ":centerPanel";

    @Inject
    private Resources resources;

    private HashMap<String, HashMap<String, String>> propertyMap;

    @PostConstruct
    private void init() {
        propertyMap = createPropertyMap();
    }

    /**
     * Creates the main menu according to the Injected Navigation map from Resources
     */
    public DefaultMenuModel createMainMenu() {

        DefaultMenuModel menu = new DefaultMenuModel();

        // Main SubMenu
        DefaultSubMenu mainMenu = new DefaultSubMenu();
        mainMenu.setLabel(SUBMENU_MAIN);
        menu.addElement(mainMenu);

        // Monitor Submenu
        DefaultSubMenu monitorMenu = new DefaultSubMenu();
        monitorMenu.setLabel(SUBMENU_MONITORS);
        menu.addElement(monitorMenu);

        // validateUrls();

        // build submenus
        for (HashMap<String, String> map : propertyMap.values()) {
            // build main menu item
            try {

                DefaultMenuItem item = createMenuItem(map.get(FIELD_TITLE), map.get(FIELD_URL));
                mainMenu.addElement(item);

                // build monitor item
                if (map.get(FIELD_MONITORING).equals("true")) {
                    String monitoringUrl = createMonitorURL(map.get(FIELD_URL));
                    DefaultMenuItem monitorItem = createMenuItem(map.get(FIELD_TITLE), monitoringUrl);
                    monitorMenu.addElement(monitorItem);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // add Ide Core Monitor
        DefaultMenuItem ideCoreMonitor = createMenuItem("IDE", IDE_CORE_MONITORING_URL);
        monitorMenu.addElement(ideCoreMonitor);

        return menu;
    }

    /**
     * Creates a single menu item and sets it's ActionListener to update the current navigation Url
     * 
     * @param value
     * @param url
     * @return
     */
    private DefaultMenuItem createMenuItem(String value, String url) {

        DefaultMenuItem item = new DefaultMenuItem();
        item.setValue(value);
        item.setIcon(MENU_ICON);
        item.setAjax(true);
        item.setParam("navigation", url);
        String command = String.format("#{layout.setNavigation('%s')}", url);
        item.setCommand(command);
        item.setUpdate(CENTER_PANEL);

        return item;
    }

    /**
     * Groups the navigation properties in a Linked Hashmap where Key = the navigation group name
     * e.g. Request Presentation Values = a Hashmap with the group fields e.g. Url, Title, Active
     * Monitoring
     * 
     * @return
     */
    private HashMap<String, HashMap<String, String>> createPropertyMap() {
        HashMap<String, HashMap<String, String>> itemMap = null;

        HashMap<String, String> navigationMap = resources.getNavigationMap();
        MultiValueMap groupMap = new MultiValueMap();

        for (String key : navigationMap.keySet()) {

            String newKey = key.split(IDE_CORE_GROUP)[1];

            Scanner sc = new Scanner(newKey).useDelimiter("\\.");
            String group = sc.next();
            groupMap.put(group, sc.next());

            sc.close();
        }

        itemMap = new LinkedHashMap<>();

        for (Object parentKey : groupMap.keySet()) {

            HashMap<String, String> childMap = new HashMap<>();

            for (Object childKey : groupMap.getCollection(parentKey)) {
                String fullKey = IDE_CORE_GROUP + parentKey + "." + childKey;
                childMap.put((String) childKey, navigationMap.get(fullKey));
            }

            itemMap.put((String) parentKey, childMap);
        }

        System.out.println("ItemMap size: " + itemMap.size());

        return itemMap;
    }

    /**
     * checks if the base Url ends with a '/' character and appends accordingly
     * 
     * @param baseUrl
     * @return
     */
    private String createMonitorURL(String baseUrl) {
        // if (!StringUtils.endsWith(baseUrl, "/")) {
        // baseUrl += "/";
        // }

        // int indexDomainUrl = StringUtils.indexOf(baseUrl, );
        String suffix = StringUtils.substring(baseUrl, Faces.getRequestDomainURL().length(), baseUrl.length() - 1);
        String moduleName = StringUtils.split(suffix, "/")[0];

        return Faces.getRequestDomainURL() + "/" + moduleName + "/" + FIELD_MONITORING;
    }

    /**
     * Creates
     */
    private void validateUrls() {

        // TODO Remove comments for old way
        // Spawn a new Thread for each url Validation
        // List<Thread> threads = new ArrayList<>(propertyMap.size());

        if (propertyMap.isEmpty())
            return;

        ExecutorService es = Executors.newFixedThreadPool(propertyMap.entrySet().size());

        for (Map.Entry<String, HashMap<String, String>> entry : propertyMap.entrySet()) {
            es.execute(new ValidatorRunnable(entry));
            // threads.add(new Thread(new ValidatorRunnable(entry)));
        }

        es.shutdown();
        try {
            es.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // alternative way to do the above with threads
        // for (Thread t : threads) {
        // t.start();
        // }
        //
        // for (Thread t : threads) {
        // try {
        // t.join();
        // } catch (InterruptedException e) {
        // e.printStackTrace();
        // }
        // }

    }

    /**
     * This private class validates the URLs in the property map and accordingly removes the invalid
     * ones
     */
    private class ValidatorRunnable implements Runnable {

        Map.Entry<String, HashMap<String, String>> entry;

        private ValidatorRunnable(Map.Entry<String, HashMap<String, String>> entry) {
            ValidatorRunnable.this.entry = entry;
        }

        @Override
        public void run() {
            String url = entry.getValue().get(FIELD_URL);
            boolean isUrlValid = isValid(url);

            if (!isUrlValid) {
                propertyMap.remove(entry.getKey());
            }
        }

        public boolean isValid(String url) {

            boolean isValid = true;

            try {
                URL u = new URL(url);
                HttpURLConnection huc = (HttpURLConnection) u.openConnection();
                huc.setRequestMethod("HEAD");
                huc.connect();
                isValid = huc.getResponseCode() == HttpURLConnection.HTTP_OK;
            } catch (IOException e) {
                e.printStackTrace();
            }
            return isValid;
        }
    }

    public String generateLogoutScript(String iframeId, String defaultNavigation) {
        Pattern pattern = Pattern.compile("(http|https)://(.*?)/(.*?)/.*");
        StringBuilder script = new StringBuilder(
                "function logoutApps() { statusDialog.show(); document.getElementById('navigation').src='");
        script.append(defaultNavigation).append("'; var ifrmWn = document.getElementById('").append(iframeId)
                .append("');\n");
        int i = 0;
        int time = 1000;
        for (HashMap<String, String> map : propertyMap.values()) {
            String url = map.get(FIELD_URL);
            Matcher matcher = pattern.matcher(url);
            if (matcher.matches()) {
                String logoutURL = url.substring(0, matcher.end(3)) + "/logout";
                if (i > 0)
                    script.append("setTimeout(function() {");
                script.append("ifrmWn.src = '").append(logoutURL).append("'");
                if (i > 0)
                    script.append(";}, ").append(time * i).append(")");
                script.append(";\n");
                i += 1;
            }
        }

        PropertyManagement props = new PropertyManagement();

        script.append(
                "setTimeout(function() {statusDialog.hide(); var link = document.getElementById('logout-link'); link.href='")
                .append(props.getCASLogoutURL()).append("'; link.click();},").append(time * i).append(");\n");
        script.append("};");
        return script.toString();
    }

}