de.ingrid.portal.scheduler.jobs.UpgradeClientJob.java Source code

Java tutorial

Introduction

Here is the source code for de.ingrid.portal.scheduler.jobs.UpgradeClientJob.java

Source

/*
 * **************************************************-
 * Ingrid Portal Apps
 * ==================================================
 * Copyright (C) 2014 - 2015 wemove digital solutions GmbH
 * ==================================================
 * Licensed under the EUPL, Version 1.1 or  as soon they will be
 * approved by the European Commission - subsequent versions of the
 * EUPL (the "Licence");
 * 
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at:
 * 
 * http://ec.europa.eu/idabc/eupl5
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the Licence is distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the Licence for the specific language governing permissions and
 * limitations under the Licence.
 * **************************************************#
 */
/*
 * Copyright (c) 1997-2006 by wemove GmbH
 */
package de.ingrid.portal.scheduler.jobs;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.SimpleHttpConnectionManager;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.Session;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import de.ingrid.portal.config.PortalConfig;
import de.ingrid.portal.hibernate.HibernateUtil;
import de.ingrid.portal.interfaces.impl.IBUSInterfaceImpl;
import de.ingrid.portal.om.IngridPartner;
import de.ingrid.portal.om.IngridProvider;
import de.ingrid.portal.upgradeclient.IngridComponent;
import de.ingrid.portal.upgradeclient.UpgradeTools;
import de.ingrid.utils.PlugDescription;

/**
 *  
 * 
 * @author andre.wallat@wemove.com
 */
public class UpgradeClientJob extends IngridMonitorAbstractJob {

    protected final static Logger log = LoggerFactory.getLogger(UpgradeClientJob.class);

    /**
     * @see org.quartz.Job#execute(org.quartz.JobExecutionContext)
     */
    @SuppressWarnings("unchecked")
    public void execute(JobExecutionContext context) throws JobExecutionException {
        // start timer
        startTimer();

        log.info("UpgradeClientJob is started ...");

        JobDataMap dataMap = context.getJobDetail().getJobDataMap();
        List<IngridComponent> installedComponents = (List<IngridComponent>) dataMap
                .get(UpgradeTools.INSTALLED_COMPONENTS);

        int status = STATUS_OK;
        String statusCode = STATUS_CODE_NO_ERROR;
        String url = null;

        try {
            url = PortalConfig.getInstance().getString(PortalConfig.UPGRADE_SERVER_URL);
            log.debug("Server-Url: " + url);

            // get atom feed with all information about available components
            Map<String, IngridComponent> serverComponents = getComponentsFromUpgrader(url);

            if (serverComponents.isEmpty()) {
                status = STATUS_ERROR;
                statusCode = STATUS_CODE_ERROR_NOT_AVAILABLE_OR_EMPTY;
            }

            // update installed components for any changes
            updateInstalledComponents(installedComponents);

            // compare list of installed one with atom feed
            updateUpgradeStatus(installedComponents, serverComponents);

            // update available types which are available on the server
            dataMap.put(UpgradeTools.COMPONENT_TYPES, getComponentTypes(serverComponents));

            // update datamap
            dataMap.put(UpgradeTools.INSTALLED_COMPONENTS, installedComponents);

        } catch (Exception e) {
            status = STATUS_ERROR;
            statusCode = STATUS_CODE_ERROR_UNSPECIFIC;
            log.error("An exception occured: " + e.getMessage());
            e.printStackTrace();
        } finally {
            computeTime(dataMap, stopTimer());
            sendEmailOnUpdate(installedComponents);
            updateJobData(context, status, statusCode);
            //context.getScheduler().addJob(context.getJobDetail(), true);
            updateJob(context);
        }
        log.info("UpgradeClientJob finished");

    }

    private Set<String> getComponentTypes(Map<String, IngridComponent> serverComponents) {
        Set<String> types = new HashSet<String>();
        Collection<IngridComponent> components = serverComponents.values();

        for (IngridComponent component : components) {
            types.add(component.getType());
        }

        return types;
    }

    private void updateInstalledComponents(List<IngridComponent> installedComponents) {
        if (installedComponents == null)
            return;

        //PlugDescription[] pds = IBUSInterfaceImpl.getInstance().getAllIPlugsWithoutTimeLimitation();
        // get all partner and provider from db to get the long name later
        Session session = HibernateUtil.currentSession();
        List<IngridProvider> allIngridProviderInDB = session.createCriteria(IngridProvider.class).list();
        List<IngridPartner> allIngridPartnerInDB = session.createCriteria(IngridPartner.class).list();

        for (IngridComponent component : installedComponents) {
            // if component is an iPlug then try to find out its version
            if (component.isIPlug()) {
                PlugDescription pd = IBUSInterfaceImpl.getInstance().getIPlug(component.getId());
                // check if component is connected in case it is an iPlug
                if (pd != null) {
                    // clear extra infos about partner and provider
                    component.removeExtraInfo(IngridComponent.PARTNER_INFO);
                    component.removeExtraInfo(IngridComponent.PROVIDER_INFO);

                    component.addExtraInfo(IngridComponent.PARTNER_INFO,
                            getTranslatedPartner(allIngridPartnerInDB, pd.getPartners()));
                    component.addExtraInfo(IngridComponent.PROVIDER_INFO,
                            getTranslatedProvider(allIngridProviderInDB, pd.getProviders()));
                    component.setVersion(pd.getMetadata() != null ? pd.getMetadata().getVersion() : "UNKNOWN");
                    // add a suffix for address-iPlugs (DSCs)
                    if (pd.getPlugId().endsWith("_addr"))
                        component.setName(pd.getDataSourceName() + "(address)");
                    else {
                        String name = pd.getDataSourceName();
                        if (name == null || name.trim().isEmpty()) {
                            name = "(no name)";
                        }
                        component.setName(name);
                    }
                    // pd.getMetadata().getReleaseDate().toString()

                    component.setConnected(STATUS_IS_AVAILABLE);
                } else {
                    component.setConnected(STATUS_NOT_AVAILABLE);
                }
            } else {
                // TODO: try to get information from the location of the installed distribution
                // ...
            }

        }
    }

    private List<String> getTranslatedPartner(List<IngridPartner> allIngridPartnerInDB, String[] partnerFromPD) {
        List<String> partners = new ArrayList<String>();
        boolean added = false;
        for (String partner : partnerFromPD) {
            added = false;
            for (IngridPartner dbPartner : allIngridPartnerInDB) {
                if (partner.equals(dbPartner.getIdent())) {
                    partners.add(dbPartner.getName());
                    added = true;
                    break;
                }
            }
            if (!added)
                partners.add(partner);
        }
        return partners;
    }

    private List<String> getTranslatedProvider(List<IngridProvider> allIngridProviderInDB,
            String[] providerFromPD) {
        List<String> providers = new ArrayList<String>();
        boolean added = false;
        for (String provider : providerFromPD) {
            added = false;
            for (IngridProvider dbProvider : allIngridProviderInDB) {
                if (provider.equals(dbProvider.getIdent())) {
                    providers.add(dbProvider.getName());
                    added = true;
                    break;
                }
            }
            // if provider cannot be found in DB use at least the identifier
            if (!added)
                providers.add(provider);
        }
        return providers;

    }

    private void updateUpgradeStatus(List<IngridComponent> installedComponents,
            Map<String, IngridComponent> serverComponents) {
        try {
            for (IngridComponent component : installedComponents) {
                if (serverComponents.containsKey(component.getType())) {
                    component.setVersionAvailable(serverComponents.get(component.getType()).getVersionAvailable());
                    component.setVersionAvailableBuild(
                            serverComponents.get(component.getType()).getVersionAvailableBuild());
                    component.setDownloadLink(serverComponents.get(component.getType()).getDownloadLink());
                    component.setChangelogLink(serverComponents.get(component.getType()).getChangelogLink());
                    // compare using build number only if it is provided in the version info of the managed component
                    // (on the client side)
                    String serverVersion = component.getVersionAvailable();
                    if (component.getVersionAvailableBuild() != "") {
                        serverVersion += " Build:" + component.getVersionAvailableBuild();
                    }
                    if (component.getVersion().compareToIgnoreCase(serverVersion) >= 0) {
                        component.setStatus(STATUS_NO_UPDATE_AVAILABLE);
                    } else {
                        component.setStatus(STATUS_UPDATE_AVAILABLE);
                    }
                    // if component is not available on the server (anymore?)
                } else {
                    component.reset();
                    component.setStatus(STATUS_NO_UPDATE_AVAILABLE);
                }
            }
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

    public Map<String, IngridComponent> getComponentsFromUpgrader(String url) {
        Map<String, IngridComponent> components = new HashMap<String, IngridComponent>();

        InputStream feed = getFeed(url);
        // return empty map if upgrade server couldn't be reached
        if (feed == null)
            return components;

        Document document = buildDocument(feed);

        NodeList entryNodes = document.getElementsByTagName("entry");

        for (int i = 0; i < entryNodes.getLength(); i++) {
            String type = findSubNode("type", entryNodes.item(i)).getTextContent();
            // if type is unknown then skip
            if (type.toLowerCase().equals("unknown")) {
                continue;
            }
            IngridComponent component = new IngridComponent(
                    findSubNode("title", entryNodes.item(i)).getTextContent(), type);

            component.setVersionAvailable(findSubNode("version", entryNodes.item(i)).getTextContent());
            component.setVersionAvailableBuild(findSubNode("build", entryNodes.item(i)).getTextContent());
            component.setDownloadLink(
                    findSubNode("link", entryNodes.item(i)).getAttributes().getNamedItem("href").getTextContent());
            Node changeLogLink = findSubNode("changelogLink", entryNodes.item(i));
            if (changeLogLink != null)
                component.setChangelogLink(findSubNode("changelogLink", entryNodes.item(i)).getTextContent());

            // only add newer version of a component
            if ((components.get(component.getType()) == null) || ((components.get(type) != null) && (components
                    .get(type).getVersionAvailable().compareToIgnoreCase(component.getVersionAvailable()) < 0))) {
                components.put(component.getType(), component);
            }
        }

        return components;
    }

    public Node findSubNode(String name, Node node) {
        if (node.getNodeType() != Node.ELEMENT_NODE) {
            log.error("Error: Search node not of element type");
            return null;
        }

        if (!node.hasChildNodes())
            return null;

        NodeList list = node.getChildNodes();
        for (int i = 0; i < list.getLength(); i++) {
            Node subnode = list.item(i);
            if (subnode.getNodeType() == Node.ELEMENT_NODE) {
                if (subnode.getNodeName().equals(name))
                    return subnode;
            }
        }
        return null;
    }

    private InputStream getFeed(String url) {
        try {
            HttpClientParams httpClientParams = new HttpClientParams();
            HttpConnectionManager httpConnectionManager = new SimpleHttpConnectionManager();
            httpClientParams.setSoTimeout(30 * 1000);
            httpConnectionManager.getParams().setConnectionTimeout(30 * 1000);
            httpConnectionManager.getParams().setSoTimeout(30 * 1000);

            HttpClient client = new HttpClient(httpClientParams, httpConnectionManager);
            HttpMethod method = new GetMethod(url);

            setCredentialsIfAny(client);

            int status = client.executeMethod(method);
            if (status == 200) {
                log.debug("Successfully received: " + url);
                return method.getResponseBodyAsStream();
            } else {
                log.error("Response code for '" + url + "' was: " + status);
                return null;
            }
        } catch (HttpException e) {
            log.error("An HTTP-Exception occured when calling: " + url + " -> " + e.getMessage());
        } catch (IOException e) {
            log.error("An IO-Exception occured when calling: " + url + " -> " + e.getMessage());
        }
        return null;
    }

    /**
     * Add username and password to the connection if it was set up in 
     * ingrid-portal-apps.properties.
     * @param client
     */
    private void setCredentialsIfAny(HttpClient client) {
        String username = PortalConfig.getInstance().getString(PortalConfig.UPGRADE_SERVER_USERNAME);
        String password = PortalConfig.getInstance().getString(PortalConfig.UPGRADE_SERVER_PASSWORD);
        if (username != null && !username.isEmpty() && password != null && !password.isEmpty()) {
            Credentials defaultcreds = new UsernamePasswordCredentials(username, password);
            //client.getState().setCredentials(new AuthScope("localhost", 80, AuthScope.ANY_REALM), defaultcreds);
            client.getState().setCredentials(AuthScope.ANY, defaultcreds);
        }
    }

    private Document buildDocument(InputStream input) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            return builder.parse(input);
        } catch (Exception e) {
            log.error("Error building document from upgrade client response", e);
            e.printStackTrace();
        }
        return null;
    }
}