com.nextep.designer.p2.services.impl.LicenseService.java Source code

Java tutorial

Introduction

Here is the source code for com.nextep.designer.p2.services.impl.LicenseService.java

Source

/*******************************************************************************
 * Copyright (c) 2011 neXtep Software and contributors.
 * All rights reserved.
 *
 * This file is part of neXtep designer.
 *
 * NeXtep designer is free software: you can redistribute it 
 * and/or modify it under the terms of the GNU General Public 
 * License as published by the Free Software Foundation, either 
 * version 3 of the License, or any later version.
 *
 * NeXtep designer 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *     neXtep Softwares - initial API and implementation
 *******************************************************************************/
package com.nextep.designer.p2.services.impl;

import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.text.MessageFormat;
import java.util.Date;

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.equinox.internal.p2.ui.dialogs.UpdateSingleIUWizard;
import org.eclipse.equinox.p2.operations.RepositoryTracker;
import org.eclipse.equinox.p2.operations.UpdateOperation;
import org.eclipse.equinox.p2.ui.LoadMetadataRepositoryJob;
import org.eclipse.equinox.p2.ui.ProvisioningUI;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.nextep.datadesigner.exception.ErrorException;
import com.nextep.designer.core.services.IRepositoryService;
import com.nextep.designer.p2.P2Messages;
import com.nextep.designer.p2.P2Plugin;
import com.nextep.designer.p2.exceptions.InvalidLicenseException;
import com.nextep.designer.p2.exceptions.UnavailableLicenseServerException;
import com.nextep.designer.p2.model.ILicenseInformation;
import com.nextep.designer.p2.model.impl.LicenseInformation;
import com.nextep.designer.p2.services.ILicenseService;

public class LicenseService implements ILicenseService {

    private final static String PROPERTY_LICENSE_KEY = "nextep.license"; //$NON-NLS-1$

    private final static Log log = LogFactory.getLog(LicenseService.class);
    private final static String DEFAULT_LICENSE_KEY = "NEXT-GPLv3-LICENSE"; //$NON-NLS-1$
    private final static String PERMISSION = "permission"; //$NON-NLS-1$
    private final static String PERMISSION_WARN = "warning"; //$NON-NLS-1$
    private final static String PERMISSION_ERROR = "error"; //$NON-NLS-1$
    private IRepositoryService repositoryService;

    @Override
    public ILicenseInformation registerLicenseKey(final String licenseKey)
            throws InvalidLicenseException, UnavailableLicenseServerException {
        final ILicenseInformation license = getLicenseFromServer(licenseKey);
        if (license == null) {
            throw new InvalidLicenseException(
                    MessageFormat.format(P2Messages.getString("service.license.invalidLicense"), //$NON-NLS-1$
                            licenseKey));
        } else {
            repositoryService.setProperty(PROPERTY_LICENSE_KEY, licenseKey);
        }
        return license;
    }

    @Override
    public URI getUpdateRepository() throws UnavailableLicenseServerException {
        try {
            final ILicenseInformation license = getCurrentLicense();
            // If none, we use the default license
            return new URI(license.getUpdateSiteLocation());
        } catch (URISyntaxException e) {
            throw new ErrorException(P2Messages.getString("service.license.invalidUpdateSite")); //$NON-NLS-1$
        }
    }

    @Override
    public ILicenseInformation getCurrentLicense() throws UnavailableLicenseServerException {
        // Trying to retrieve license key from repository
        String licenseKey = repositoryService.getProperty(PROPERTY_LICENSE_KEY);
        ILicenseInformation license = null;
        if (licenseKey == null || "".equals(licenseKey)) { //$NON-NLS-1$
            licenseKey = DEFAULT_LICENSE_KEY;
        }
        // Querying the license server to get the update site
        license = getLicenseFromServer(licenseKey);
        return license;
    }

    private ILicenseInformation getLicenseFromServer(String licenseKey) throws UnavailableLicenseServerException {
        String uri = buildRequest(licenseKey, false);
        ILicenseInformation licenseInfo = null;
        try {
            licenseInfo = getLicenseFromUrl(licenseKey, uri);
        } catch (UnavailableLicenseServerException e) {
            log.error("Unable to reach nextep server URL " + uri + ": " + e.getMessage(), e); //$NON-NLS-1$//$NON-NLS-2$
        } catch (RuntimeException e) {
            log.error("Unable to reach nextep server URL " + uri + ": " + e.getMessage(), e); //$NON-NLS-1$//$NON-NLS-2$
        }
        if (licenseInfo == null) {
            // Trying direct access (existing clients may have only authorized
            // this access on their proxy)
            uri = buildRequest(licenseKey, true);
            licenseInfo = getLicenseFromUrl(licenseKey, uri);
        }
        return licenseInfo;
    }

    private ILicenseInformation getLicenseFromUrl(String licenseKey, String uri)
            throws UnavailableLicenseServerException {

        // As we don't have CXF WebClient here for connect & parse, we use the
        // old doc builder way
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(uri);
            Element elt = doc.getDocumentElement();
            NodeList list = elt.getElementsByTagName("license"); //$NON-NLS-1$
            Element license = (Element) list.item(0);
            if (license != null) {
                NodeList urls = license.getElementsByTagName("updateUrl"); //$NON-NLS-1$
                Element updateUrlElt = (Element) urls.item(0);
                String updateUrl = updateUrlElt.getTextContent();

                NodeList organizations = license.getElementsByTagName("organization"); //$NON-NLS-1$
                String organization = ((Element) organizations.item(0)).getTextContent();

                NodeList contactEmails = license.getElementsByTagName("contactEmail"); //$NON-NLS-1$
                String contactEmail = "unknown";
                if (contactEmails != null && contactEmails.getLength() > 0) {
                    contactEmail = ((Element) contactEmails.item(0)).getTextContent();
                }

                NodeList contactNames = license.getElementsByTagName("contactName"); //$NON-NLS-1$
                String contactName = null;
                if (contactNames != null && contactNames.getLength() > 0) {
                    contactName = ((Element) contactNames.item(0)).getTextContent();
                }

                //            NodeList validFromNode = license.getElementsByTagName("validFrom"); //$NON-NLS-1$
                // long validFrom = Long.parseLong(((Element)
                // validFromNode.item(0)).getTextContent());
                // Date validFromDate = new Date(validFrom);

                NodeList validUntilNode = license.getElementsByTagName("validUntil"); //$NON-NLS-1$
                long validUntil = Long.parseLong(((Element) validUntilNode.item(0)).getTextContent());
                Date validUntilDate = new Date(validUntil);

                NodeList permissions = license.getElementsByTagName(PERMISSION);
                if (permissions != null && permissions.getLength() > 0) {
                    String val = permissions.item(0).getTextContent();
                    if (PERMISSION_WARN.equals(val)) {
                        String msgKey = "preferences.license.licenseExpiredMsg"; //$NON-NLS-1$
                        if (validUntil > System.currentTimeMillis()) {
                            msgKey = "preferences.license.licenseQuotaMsg"; //$NON-NLS-1$
                        }
                        // Injecting contact email and name into warning message
                        final String dlgMsg = MessageFormat.format(P2Messages.getString(msgKey), contactName,
                                contactEmail);

                        // Popping our dialog
                        Display.getDefault().syncExec(new Runnable() {

                            @Override
                            public void run() {
                                MessageDialog.openWarning(null,
                                        P2Messages.getString("preferences.license.licenseExpiredTitle"), //$NON-NLS-1$
                                        dlgMsg);

                            }
                        });
                    } else if (PERMISSION_ERROR.equals(val)) {
                        String msgKey = "preferences.license.licenseExpiredError"; //$NON-NLS-1$
                        if (validUntil > System.currentTimeMillis()) {
                            msgKey = "preferences.license.licenseQuotaError"; //$NON-NLS-1$
                        }
                        // Injecting contact email and name into warning message
                        final String dlgMsg = MessageFormat.format(P2Messages.getString(msgKey), contactName,
                                contactEmail);
                        Display.getDefault().syncExec(new Runnable() {

                            @Override
                            public void run() {
                                MessageDialog.openWarning(null,
                                        P2Messages.getString("preferences.license.licenseExpiredTitle"), //$NON-NLS-1$
                                        dlgMsg);
                                System.exit(-1);
                            }
                        });
                    }
                }
                LicenseInformation info = new LicenseInformation();
                info.setUpdateSiteLocation(updateUrl);
                info.setLicenseKey(licenseKey);
                info.setOrganization(organization);
                info.setExpirationDate(validUntilDate);
                return info;
            }
        } catch (RuntimeException e) {
            throw new UnavailableLicenseServerException(
                    P2Messages.getString("service.license.unexpectedException") + e.getMessage(), e); //$NON-NLS-1$
        } catch (Exception e) {
            throw new UnavailableLicenseServerException(
                    P2Messages.getString("service.license.serverProblemException") + e.getMessage(), e); //$NON-NLS-1$
        }
        throw new UnavailableLicenseServerException(
                MessageFormat.format(P2Messages.getString("service.license.unregisteredLicense"), //$NON-NLS-1$
                        licenseKey));
    }

    /**
     * Builds the request URI to the license server
     * 
     * @param licenseKey
     *            license key to query
     * @return the URI of the request to the license server
     */
    private String buildRequest(String licenseKey, boolean direct) {
        final String version = P2Plugin.getDefault().getBundle().getVersion().toString();
        String ipAddress = ""; //$NON-NLS-1$
        try {
            ipAddress = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {

        }

        // Preserving direct and indirect access to preserve compatibility for
        // pre 1.0.7 users
        // accessing license servers from direct calls who may have configured
        // their proxy
        // for this exact path. As we do need to secure our connection to our
        // license servers.
        final StringBuilder buf = new StringBuilder();
        if (direct) {
            buf.append("http://www.nextep-softwares.com:8282"); //$NON-NLS-1$
        } else {
            buf.append("http://license.nextep-softwares.com"); //$NON-NLS-1$
        }
        buf.append("/license/ws/licenseInfo/" + licenseKey + "/" //$NON-NLS-1$ //$NON-NLS-2$
                + ipAddress + "/" + version //$NON-NLS-1$
        );
        if (!direct) {
            buf.append("-direct"); //$NON-NLS-1$
        }

        return buf.toString();
    }

    @Override
    public void checkForUpdates(final boolean isSilent) {
        final RepositoryTracker repoMan = getProvisioningUI().getRepositoryTracker();

        // Checking whether the update site is available
        Job j = new Job("Checking for updates...") {

            @Override
            protected IStatus run(org.eclipse.core.runtime.IProgressMonitor monitor) {
                if (repoMan.getKnownRepositories(getProvisioningUI().getSession()).length == 0) {
                    if (!isSilent) {
                        MessageDialog.openWarning(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
                                P2Messages.getString("service.license.serverUnavailableTitle"), //$NON-NLS-1$
                                P2Messages.getString("service.license.serverUnavailableMsg")); //$NON-NLS-1$
                    } else {
                        log.info(P2Messages.getString("service.license.serverUnavailableSilent")); //$NON-NLS-1$
                    }
                    return Status.CANCEL_STATUS;
                }

                // We are clear for update check
                Job.getJobManager().cancel(LoadMetadataRepositoryJob.LOAD_FAMILY);
                final LoadMetadataRepositoryJob loadJob = new LoadMetadataRepositoryJob(getProvisioningUI());
                loadJob.setProperty(LoadMetadataRepositoryJob.ACCUMULATE_LOAD_ERRORS, Boolean.toString(true));

                loadJob.addJobChangeListener(new JobChangeAdapter() {

                    @Override
                    public void done(IJobChangeEvent event) {
                        if (PlatformUI.isWorkbenchRunning())
                            if (event.getResult().isOK()) {

                                performUpdateCheck(loadJob, isSilent);
                            }
                    }
                });
                loadJob.setUser(!isSilent);
                loadJob.schedule();
                return Status.OK_STATUS;
            }
        };
        j.schedule();
    }

    private void performUpdateCheck(final LoadMetadataRepositoryJob job, final boolean isSilent) {
        // Retrieving update site
        try {
            final URI updateSiteLocation = P2Plugin.getService(ILicenseService.class).getUpdateRepository();
            final UpdateOperation operation = getProvisioningUI().getUpdateOperation(null,
                    new URI[] { updateSiteLocation });
            // check for updates
            operation.resolveModal(null);
            // If we are in silent mode, we only continue if we have any update
            if (isSilent) {
                final IStatus status = operation.getResolutionResult();
                if (status.getCode() == UpdateOperation.STATUS_NOTHING_TO_UPDATE
                        || status.getSeverity() == IStatus.CANCEL) {
                    return;
                }
            }
            Display.getDefault().syncExec(new Runnable() {

                @SuppressWarnings("restriction")
                @Override
                public void run() {
                    // Getting shell
                    final Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
                    if (getProvisioningUI().getPolicy().continueWorkingWithOperation(operation, shell)) {

                        if (UpdateSingleIUWizard.validFor(operation)) {
                            // Special case for only updating a single root
                            UpdateSingleIUWizard wizard = new UpdateSingleIUWizard(getProvisioningUI(), operation);
                            WizardDialog dialog = new WizardDialog(shell, wizard);
                            dialog.create();
                            dialog.open();
                        } else {
                            // Open the normal version of the update wizard
                            getProvisioningUI().openUpdateWizard(false, operation, job);
                        }

                    }
                };
            });
        } catch (UnavailableLicenseServerException e) {
            log.error(P2Messages.getString("service.license.serverUnavailableWithReason") //$NON-NLS-1$
                    + e.getMessage(), e);
        }
    }

    protected ProvisioningUI getProvisioningUI() {
        return ProvisioningUI.getDefaultUI();
    }

    public void setRepositoryService(IRepositoryService service) {
        this.repositoryService = service;
    }
}