com.ibm.domino.osgi.debug.launch.AbstractDominoOSGILaunchConfiguration.java Source code

Java tutorial

Introduction

Here is the source code for com.ibm.domino.osgi.debug.launch.AbstractDominoOSGILaunchConfiguration.java

Source

/*
*  Copyright IBM Corp. 2012
* 
* 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 com.ibm.domino.osgi.debug.launch;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.internal.core.PDEState;
import org.eclipse.pde.internal.core.PluginPathFinder;
import org.eclipse.pde.launching.EquinoxLaunchConfiguration;
import org.eclipse.pde.launching.IPDELauncherConstants;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;

import com.ibm.domino.osgi.debug.utils.StringUtil;

/**
 * @author dtaieb
 * @author doconnor
 * 
 * An abstract Eclipse OSGi Framework launch configuration.
 * Configurations extending from this class will modify the Domino OSGi
 * configration.
 */
@SuppressWarnings("restriction")

public abstract class AbstractDominoOSGILaunchConfiguration extends EquinoxLaunchConfiguration {

    private IPluginModelBase osgiFrameworkModel;

    /**
     * 
     */
    public AbstractDominoOSGILaunchConfiguration() {
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.pde.launching.AbstractPDELaunchConfiguration#launch(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, org.eclipse.debug.core.ILaunch, org.eclipse.core.runtime.IProgressMonitor)
     */
    @Override
    public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor)
            throws CoreException {
        try {
            doLaunch(configuration, mode, launch, monitor);
        } finally {
            //For now we don't connect to the Domino JVM process, so manually remove the launch from debug perspective otherwise it will stay there forever
            DebugPlugin.getDefault().getLaunchManager().removeLaunch(launch);
        }
    }

    private class AbortException extends RuntimeException {
        private static final long serialVersionUID = 1L;
    }

    /**
     * @param configuration
     * @param mode
     * @param launch
     * @param monitor
     */
    private void doLaunch(ILaunchConfiguration configuration, String mode, ILaunch launch,
            IProgressMonitor monitor) {
        try {
            boolean autostart = configuration.getAttribute(IPDELauncherConstants.DEFAULT_AUTO_START, true);
            if (autostart) {
                //Auto-start must be set to false!
                PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
                    public void run() {
                        String dialogTitle = "Error";
                        String dialogMessage = "The \"Default Auto-Start\" attribute within your {0} configuration must be set to \"false\". A value of \"true\" has been detected.\n\nThe configuration will not be applied!";
                        dialogMessage = MessageFormat.format(dialogMessage,
                                AbstractDominoOSGILaunchConfiguration.this.getName());
                        Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();

                        MessageDialog.openError(shell, dialogTitle, dialogMessage);
                    }
                });
                return;
            }
            final DominoOSGIConfig config = new DominoOSGIConfig(this, getWorkspaceRelativePath());
            PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
                public void run() {
                    new DominoOSGIConfigCreateDialog(config,
                            PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell()).open();
                }
            });

            if (config.getReturnCode() == IDialogConstants.CANCEL_ID) {
                return;
            }

            //Call preLaunchCheck to fill the bundleMap
            try {
                preLaunchCheck(configuration, launch, new SubProgressMonitor(monitor, 2));
            } catch (CoreException e) {
                if (e.getStatus().getSeverity() == IStatus.CANCEL) {
                    monitor.setCanceled(true);
                    return;
                }
                throw e;
            }
            getProgramArguments(configuration);

            //Update the config.ini with any environment variables set by the configuration
            updateConfigIni(config, configuration);

            //Create the pde.launch.ini
            createPDELaunchIni(config, configuration);

            PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
                public void run() {
                    Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
                    try {
                        MessageDialog.openInformation(shell, "Success",
                                MessageFormat.format(
                                        "Successfully updated \"{0}\".\nTo run normally, please delete this file.",
                                        getPDELaunchIni(config).getAbsolutePath()));
                    } catch (IOException e) {
                        MessageDialog.openError(shell, "Error", e.getMessage());
                    }
                }
            });

        } catch (final Exception e) {
            monitor.setCanceled(true);
            Display.getDefault().syncExec(new Runnable() {
                public void run() {
                    String message = e.getMessage();
                    if (e instanceof AbortException) {
                        message = "Domino OSGi launch configuration aborted by user";
                    }
                    MessageDialog.openError(null, "error", message);
                }
            });
        }
    }

    /**
     * @param configuration
     * @return
     * @throws CoreException
     */
    private boolean isTargetPlatformPluginsDisabled(ILaunchConfiguration configuration) throws CoreException {
        String selectedTargetBundles = configuration.getAttribute(IPDELauncherConstants.TARGET_BUNDLES,
                (String) null);
        return selectedTargetBundles == null || selectedTargetBundles.length() == 0;
    }

    /**
     * @param config
     * @param configuration
     * @throws CoreException
     * @throws IOException
     */
    private void updateConfigIni(DominoOSGIConfig config, ILaunchConfiguration configuration)
            throws CoreException, IOException {
        File configIni = new File(getConfigDir(configuration), "config.ini");
        if (!configIni.exists()) {
            //No config ini to update
            return;
        }

        Map<String, String> envMap = configuration.getAttribute("org.eclipse.debug.core.environmentVariables",
                (Map<String, String>) null);
        if (envMap != null) {
            //Add all the env variables that start with "domino.osgi" to the config.ini
            Map<String, String> dominoVars = new HashMap<String, String>();
            for (String key : envMap.keySet()) {
                if (key.startsWith("domino.osgi")) {
                    String value = envMap.get(key);
                    dominoVars.put(key, value);
                }
            }

            if (!dominoVars.isEmpty()) {
                FileWriter fw = null;
                try {
                    fw = new FileWriter(configIni, true);
                    for (String key : dominoVars.keySet()) {
                        fw.append(key + "=" + dominoVars.get(key));
                    }
                } finally {
                    if (fw != null) {
                        fw.close();
                    }
                }
            }
        }

        if (isTargetPlatformPluginsDisabled(configuration)) {
            //Load the properties from config.ini
            Properties props = new Properties();
            FileInputStream fis = null;
            try {
                props.load(fis = new FileInputStream(configIni));
            } finally {
                if (fis != null) {
                    fis.close();
                }
            }

            String osgiBundles = props.getProperty("osgi.bundles");

            //Get the osgi.bundles key and augment it
            String binPath = config.getDominoBinPath();
            binPath = prunePath(binPath);
            String targetBundles = computeTargetBundles(fAllBundles,
                    binPath + "/" + getOSGIDirectoryName() + "/rcp/eclipse");
            if (targetBundles != null && targetBundles.length() > 0) {
                if (osgiBundles == null) {
                    osgiBundles = targetBundles;
                } else {
                    osgiBundles = targetBundles + "," + osgiBundles;
                }
            }

            targetBundles = computeTargetBundles(fAllBundles,
                    binPath + "/" + getOSGIDirectoryName() + "/shared/eclipse");
            if (targetBundles != null && targetBundles.length() > 0) {
                if (osgiBundles == null) {
                    osgiBundles = targetBundles;
                } else {
                    osgiBundles = osgiBundles + "," + targetBundles;
                }
            }
            String dataPath = config.getDominoDataPath();
            dataPath = prunePath(dataPath);
            targetBundles = computeTargetBundles(fAllBundles,
                    dataPath + "/" + getWorkspaceRelativePath() + "/applications/eclipse");
            if (targetBundles != null && targetBundles.length() > 0) {
                if (osgiBundles == null) {
                    osgiBundles = targetBundles;
                } else {
                    osgiBundles = osgiBundles + "," + targetBundles;
                }
            }
            /*
             * Read all of the .link files - this will add the Upgrade Pack plugins to the config
             */
            File linksDir = new File(binPath + "/" + getOSGIDirectoryName() + "/rcp/eclipse/links");
            if (linksDir.exists() && linksDir.isDirectory()) {
                File[] links = linksDir.listFiles();
                if (links != null) {
                    for (File link : links) {
                        FileReader reader = new FileReader(link);
                        BufferedReader lineReader = new BufferedReader(reader);
                        String linkPath = lineReader.readLine();
                        if (!StringUtil.isEmpty(linkPath)) {
                            if (linkPath.indexOf('=') != -1) {
                                linkPath = linkPath.substring(linkPath.indexOf('=') + 1);
                                int index = linkPath.indexOf(':');
                                if (index != -1) {
                                    if (linkPath.charAt(index - 1) == '\\') {
                                        linkPath = linkPath.substring(0, index - 1) + linkPath.substring(index);
                                    }
                                    linkPath = prunePath(linkPath);
                                    linkPath = linkPath + "/eclipse";
                                    targetBundles = computeTargetBundles(fAllBundles, linkPath);
                                    if (targetBundles != null && targetBundles.length() > 0) {
                                        if (osgiBundles == null) {
                                            osgiBundles = targetBundles;
                                        } else {
                                            osgiBundles = osgiBundles + "," + targetBundles;
                                        }
                                    }
                                }
                            }

                        }
                    }
                }
            }

            //Add the dynamically generated fragment to the system bundle
            String systemFragment = getSystemFragmentFileName();
            if (systemFragment != null) {
                osgiBundles += ",reference:file:" + dataPath + "/" + getWorkspaceRelativePath()
                        + "/.config/domino/eclipse/plugins/" + systemFragment;
            }

            props.setProperty("osgi.bundles", osgiBundles);

            props.setProperty("osgi.install.area",
                    "file:" + binPath + "/" + getOSGIDirectoryName() + "/rcp/eclipse");
            if (osgiFrameworkModel != null) {
                props.put("osgi.framework", getBundleURL(osgiFrameworkModel, false));
            }

            //Save the configuration
            FileOutputStream fos = null;
            try {
                props.store(fos = new FileOutputStream(configIni), "");
            } finally {
                if (fos != null) {
                    fos.close();
                }
            }
        }
    }

    protected String prunePath(String path) {
        if (!StringUtil.isEmpty(path)) {
            if (path.endsWith("/") || path.endsWith("\\")) {
                return path.substring(0, path.length() - 1);
            }
        }
        return path;
    }

    /**
     * @param osgiFrameworkModel2
     * @param b
     * @return
     */
    private String getBundleURL(IPluginModelBase model, boolean bIncludeRefence) {
        if (model == null || model.getInstallLocation() == null) {
            return null;
        }
        try {
            return getBundleFromHelper("org.eclipse.pde.internal.ui.launcher.LaunchConfigurationHelper", model,
                    bIncludeRefence);
        } catch (Throwable t) {
            //We may be in a 3.6 eclipse, LaunchConfigurationHelper has moved to another package
            try {
                return getBundleFromHelper("org.eclipse.pde.internal.launching.launcher.LaunchConfigurationHelper",
                        model, bIncludeRefence);
            } catch (Throwable e) {
                //Fallback
                StringBuilder sb = new StringBuilder();
                if (bIncludeRefence) {
                    sb.append("reference:");
                }
                sb.append("file:");
                sb.append(new Path(model.getInstallLocation()).removeTrailingSeparator().toString());
                return sb.toString();
            }
        }
    }

    /**
     * @param className
     * @param model
     * @param bIncludeRefence
     * @return
     * @throws Throwable
     */
    private String getBundleFromHelper(String className, IPluginModelBase model, boolean bIncludeRefence)
            throws Throwable {
        Class<?> helper = Class.forName(className);
        Method m = helper.getMethod("getBundleURL", IPluginModelBase.class, Boolean.TYPE);

        return (String) m.invoke(null, model, bIncludeRefence);
    }

    /**
     * @param workspacePlugins
     * @param eclipseLocation
     * @return
     */
    private String computeTargetBundles(Map<?, ?> workspacePlugins, String eclipseLocation) {
        URL[] pluginPaths = PluginPathFinder.getPluginPaths(eclipseLocation, false);
        PDEState pdeState = new PDEState(pluginPaths, true, true, new NullProgressMonitor());
        IPluginModelBase[] models = pdeState.getTargetModels();
        return getTargetBundles(workspacePlugins, models);
    }

    /**
     * @param workspacePlugins
     * @param models
     * @return
     */
    private String getTargetBundles(Map<?, ?> workspacePlugins, IPluginModelBase[] models) {
        StringBuffer buffer = new StringBuffer();
        for (IPluginModelBase model : models) {
            String id = model.getPluginBase().getId();
            //         if ( "com.ibm.pvc.servlet".equals( id ) ){
            //            continue;
            //         }
            if (workspacePlugins.containsKey(id)) {
                if ("org.eclipse.osgi".equals(id)) {
                    osgiFrameworkModel = model;
                }
                //already selected, continue
                continue;
            }
            if (!"org.eclipse.osgi".equals(id)) {
                if (buffer.length() > 0) {
                    buffer.append(",");
                }
                buffer.append(getBundleURL(model, true));

                //            if ( "org.eclipse.update.configurator".equals( id )){
                //               buffer.append("@3:start");
                //            }else 
                if ("org.eclipse.equinox.common".equals(id)) {
                    buffer.append("@2:start");
                } else if ("org.eclipse.core.runtime".equals(id)) {
                    buffer.append("@start");
                } else if ("org.eclipse.equinox.common".equals(id)) {
                    buffer.append("@2:start");
                } else if ("org.eclipse.core.jobs".equals(id)) {
                    buffer.append("@4:start");
                } else if ("org.eclipse.equinox.registry".equals(id)) {
                    buffer.append("@4:start");
                } else if ("org.eclipse.equinox.preferences".equals(id)) {
                    buffer.append("@4:start");
                }
            } else {
                osgiFrameworkModel = model;
            }
        }
        return buffer.toString();
    }

    /**
     * @param configuration
     * @throws IOException
     */
    private void createPDELaunchIni(DominoOSGIConfig osgiConfig, ILaunchConfiguration configuration)
            throws IOException {
        File pdeLaunchIniFile = getPDELaunchIni(osgiConfig);
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(pdeLaunchIniFile);
            Properties props = new Properties();
            props.setProperty("configuration", configuration.getName());
            props.setProperty("osgi.configuration.area",
                    getConfigDir(configuration).getAbsolutePath().replace('\\', '/'));
            props.store(fos, "Generated by IBM Lotus Domino OSGi Debug Plug-in");
        } finally {
            if (fos != null) {
                fos.close();
            }
        }
    }

    /**
     * @param osgiConfig
     * @return
     * @throws IOException
     */
    private File getPDELaunchIni(DominoOSGIConfig osgiConfig) throws IOException {
        File notesDataDir = new File(osgiConfig.getDominoDataPath());
        if (!notesDataDir.exists()) {
            throw new IOException(
                    MessageFormat.format("Data directory does not exist {0}", osgiConfig.getDominoDataPath()));
        }
        final File dominoWorkspaceDir = new File(notesDataDir, getWorkspaceRelativePath());
        if (!dominoWorkspaceDir.exists() || !dominoWorkspaceDir.isDirectory()) {
            PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
                public void run() {
                    Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
                    boolean bCreate = MessageDialog.openQuestion(shell, "Question", MessageFormat.format(
                            "The directory \"{0}\" does not exist.\nThis may be because the OSGi configuration has never been run previously.\nWould you like to create it?",
                            dominoWorkspaceDir.getAbsolutePath()));
                    if (bCreate) {
                        dominoWorkspaceDir.mkdirs();
                    }
                }
            });
        }

        if (!dominoWorkspaceDir.exists() || !dominoWorkspaceDir.isDirectory()) {
            throw new AbortException();
        }
        return new File(dominoWorkspaceDir, "pde.launch.ini");
    }

    /**
     * @return
     */
    protected abstract String getWorkspaceRelativePath();

    /**
     * @return
     */
    protected abstract String getOSGIDirectoryName();

    /**
     * @return
     */
    public abstract String[] getProfiles();

    /**
     * @param selectedProfile
     */
    public abstract void setProfile(String selectedProfile);

    public abstract String getName();

    protected abstract String getSystemFragmentFileName();
}