/******************************************************************************* * Copyright (c) 2016 Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.browsersim.reddeer; import java.io.File; import java.io.IOException; import java.rmi.NoSuchObjectException; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.Platform; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.core.model.IProcess; import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; import org.eclipse.pde.internal.core.exports.PluginExportOperation; import org.eclipse.pde.core.plugin.IPluginModelBase; import org.eclipse.pde.core.plugin.PluginRegistry; import org.eclipse.pde.internal.core.exports.FeatureExportInfo; import org.jboss.reddeer.common.condition.AbstractWaitCondition; import org.jboss.reddeer.common.wait.TimePeriod; import org.jboss.reddeer.common.wait.WaitUntil; import org.jboss.reddeer.swt.api.ToolItem; import org.jboss.reddeer.swt.impl.menu.ContextMenu; import org.jboss.tools.browsersim.eclipse.launcher.BrowserSimLauncher; import org.jboss.tools.browsersim.eclipse.launcher.ExternalProcessLauncher; import org.jboss.tools.browsersim.reddeer.condition.LaunchExists; import org.jboss.tools.browsersim.rmi.BrowsersimUtil; import org.jboss.tools.browsersim.rmi.IBrowsersimHandler; import org.jboss.tools.browsersim.rmi.MySecurityManager; import org.osgi.framework.Bundle; public class SimLauncher { protected static Registry registry; private static final String HAMCREST_BUNDLE = "org.hamcrest.core"; private static ILaunch simLaunch; protected void stopRMIRegistry() { try { UnicastRemoteObject.unexportObject(registry, true); } catch (NoSuchObjectException e) { e.printStackTrace(); } } protected void startRMIRegistry(String rmiCodebase) { try { if(System.getSecurityManager() == null){ System.setSecurityManager(new MySecurityManager()); } if(rmiCodebase != null){ System.setProperty("java.rmi.server.codebase",rmiCodebase); } registry = LocateRegistry.createRegistry(1099); } catch (RemoteException ex) { try { registry = LocateRegistry.getRegistry(1099); IBrowsersimHandler bsHandler = (IBrowsersimHandler) registry.lookup(BrowsersimUtil.BS_HANDLER); UnicastRemoteObject.unexportObject(bsHandler, true); registry.unbind(BrowsersimUtil.BS_HANDLER); } catch (Exception e) { e.printStackTrace(); } } } protected ILaunchConfigurationWorkingCopy getSimLaunchConfig(ContextMenu menu, ToolItem item) { BrowserSimLaunchListener launchListener = new BrowserSimLaunchListener(); ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); manager.addLaunchListener(launchListener); if (menu != null) { menu.select(); } else { item.click(); } new WaitUntil(new LaunchExists(launchListener)); IProcess[] processes = launchListener.getBrowserSimLaunch().getProcesses(); try { processes[0].terminate(); } catch (DebugException e1) { throw new BrowserSimException("Unable to terminate *Sim", e1); } launchListener.getBrowserSimLaunch().removeProcess(processes[0]); try { return launchListener.getBrowserSimLaunch().getLaunchConfiguration().getWorkingCopy(); } catch (CoreException e) { throw new BrowserSimException("Unable to obtain *Sim launch configuration", e); } } protected void launchSimWithRMI(List<Bundle> additionalBundles, String mainClass, ContextMenu menu, ToolItem item) { ILaunchConfigurationWorkingCopy wc = getSimLaunchConfig(menu, item); try { List<String> classPath = wc.getAttribute(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH, new ArrayList<String>()); Bundle hamcrest = Platform.getBundle(HAMCREST_BUNDLE); String hamcrestLocation = FileLocator.getBundleFile(hamcrest).getCanonicalPath(); List<String> mem = ExternalProcessLauncher.getClassPathMementos(hamcrestLocation); deleteDir(new File("target/bundleBuild")); List<String> additionalBundlesFinalLoc = exportAndGetBundlePath(additionalBundles); for(String additionalBundle: additionalBundlesFinalLoc){ mem.addAll(ExternalProcessLauncher.getClassPathMementos(additionalBundle)); } //temp for testing changes in cordovasim plugins List<String> cpTemp = new ArrayList<>(classPath); classPath = new ArrayList<>(); for(String cp: cpTemp){ String[] a = cp.split("externalArchive"); String[] b = a[1].split("path"); String[] c = b[0].split("="); String[] d = c[1].split("\""); String archivePath = cp.split("externalArchive")[1].split("path")[0].split("=")[1].split("\"")[1]; String archiveName; if(archivePath.endsWith("bin")){ archiveName = archivePath.split("_")[0].split("/")[archivePath.split("_")[0].split("/").length-2]; } else { archiveName = archivePath.split("_")[0].split("/")[archivePath.split("_")[0].split("/").length-1]; } ; String exportedBundlePath = exportAndGetBundlePath(archivePath,archiveName); if(exportedBundlePath == null){ classPath.add(cp); } else{ classPath.addAll(ExternalProcessLauncher.getClassPathMementos(exportedBundlePath)); } } /// classPath.addAll(mem); wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH, classPath); wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, mainClass); List<String> bsBundles = BrowserSimLauncher.getBundles(); bsBundles.addAll(BrowserSimLauncher.getJettyBundles()); StringBuilder allBundlesBuilder = new StringBuilder(); for(String bsBundle: bsBundles){ Bundle b = Platform.getBundle(bsBundle); allBundlesBuilder.append("file://"+FileLocator.getBundleFile(b).getCanonicalPath()+" "); } for(String additionalFinal: additionalBundlesFinalLoc){ allBundlesBuilder.append("file://"+additionalFinal+" "); } startRMIRegistry(allBundlesBuilder.toString()); simLaunch = wc.launch(ILaunchManager.RUN_MODE, null); } catch (CoreException | IOException e) { throw new BrowserSimException("Unable to start *Sim", e); } } private List<String> exportAndGetBundlePath(List<Bundle> bundles) throws IOException{ List<String> bundlesFileLocation = new ArrayList<>(); for(Bundle additionalBundle: bundles){ String aBundleLocation = FileLocator.getBundleFile(additionalBundle).getCanonicalPath(); //check if bundle is folder or jar if(!aBundleLocation.endsWith("jar")){ //export folder to jar String bundleLoc = export(additionalBundle); File bundleLocFile = new File(bundleLoc); new WaitUntil(new BundleIsExported(bundleLocFile,additionalBundle.getSymbolicName()), TimePeriod.LONG); for(File f: bundleLocFile.listFiles()){ if(f.getName().contains(additionalBundle.getSymbolicName())){ aBundleLocation = f.getAbsolutePath(); } } } bundlesFileLocation.add(aBundleLocation); } return bundlesFileLocation; } private String exportAndGetBundlePath(String bundlePath, String name) throws IOException{ //check if bundle is folder or jar if(!bundlePath.endsWith("jar")){ //export folder to jar String bundleLoc = export(name); File bundleLocFile = new File(bundleLoc); new WaitUntil(new BundleIsExported(bundleLocFile,name), TimePeriod.LONG); for(File f: bundleLocFile.listFiles()){ if(f.getName().contains(name)){ return f.getAbsolutePath(); } } } return null; } private String export(String bundleName){ File bundleBuildDir = new File("target/bundleBuild"); IPluginModelBase pb = PluginRegistry.findModel(bundleName); FeatureExportInfo info = new FeatureExportInfo(); info.toDirectory = true; info.useJarFormat = true; info.exportSource = false; info.exportSourceBundle = true; info.allowBinaryCycles = true; info.useWorkspaceCompiledClasses = false; String bungleTargetLoc = bundleBuildDir.getAbsolutePath(); info.destinationDirectory = bungleTargetLoc; info.zipFileName = null; info.items = new Object[] {pb}; info.signingInfo = null; info.qualifier = null; PluginExportOperation peo = new PluginExportOperation(info, bundleName); peo.schedule(); try { peo.join(); //wait for job to finish } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return bungleTargetLoc+"/plugins/"; } protected String export(Bundle bundle){ File bundleBuildDir = new File("target/bundleBuild"); IPluginModelBase pb = PluginRegistry.findModel(bundle.getSymbolicName()); FeatureExportInfo info = new FeatureExportInfo(); info.toDirectory = true; info.useJarFormat = true; info.exportSource = false; info.exportSourceBundle = true; info.allowBinaryCycles = true; info.useWorkspaceCompiledClasses = false; String bungleTargetLoc = bundleBuildDir.getAbsolutePath(); info.destinationDirectory = bungleTargetLoc; info.zipFileName = null; info.items = new Object[] {pb}; info.signingInfo = null; info.qualifier = null; PluginExportOperation peo = new PluginExportOperation(info, bundle.getSymbolicName()); peo.schedule(); try { peo.join(); //wait for job to finish } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return bungleTargetLoc+"/plugins/"; } public static boolean deleteDir(File dir) { if (dir.isDirectory()) { String[] children = dir.list(); for (int i = 0; i < children.length; i++) { boolean success = deleteDir(new File(dir, children[i])); if (!success) { return false; } } } return dir.delete(); // The directory is empty now and can be deleted. } protected static void stopSim() { if (simLaunch == null) { throw new BrowserSimException("*Sim launch does not exist"); } try { if(simLaunch.getProcesses()[0].isTerminated()){ throw new BrowserSimException("*Sim process is already terminated"); } simLaunch.getProcesses()[0].terminate(); simLaunch.terminate(); simLaunch = null; } catch (DebugException e) { throw new BrowserSimException("Unable to terminate *Sim process",e); } } private class BundleIsExported extends AbstractWaitCondition { private File bundleFolder; private String bundleName; public BundleIsExported(File bundleFolder,String bundleName) { this.bundleFolder = bundleFolder; this.bundleName = bundleName; } @Override public boolean test() { if(bundleFolder.exists()){ for(File f: bundleFolder.listFiles()){ if(f.getName().contains(bundleName)){ return true; } } } return false; } @Override public String description() { return bundleName +" is exported"; } } }