/******************************************************************************* * Copyright (c) 2010 Freescale Semiconductor. * All rights reserved. This program and the accompanying materials * are 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: * Serge Beauchamp (Freescale Semiconductor) - initial API and implementation *******************************************************************************/ package com.freescale.deadlockpreventer.agent; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Text; import com.freescale.deadlockpreventer.agent.IAgent.IProcess; public class StandaloneConfigurator implements IConfigurator { IAgent agent; private Button launch; private Button browse; private Text executablePath; private boolean launching = false; private ArrayList<String> previousLines; @Override public void initialize(IAgent agent) { this.agent = agent; } @Override public String getName() { return "External Eclipse layout"; } @Override public void createPartControl(Composite parent) { createLauncherPart(parent); } private void createLauncherPart(Composite group) { group.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); GridLayout layout = new GridLayout(2, false); group.setLayout(layout); executablePath = new Text(group, SWT.BORDER); executablePath.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); executablePath.setText(agent.getPref(IAgent.PREF_INSTALLATION_DIR, new String())); executablePath.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { File eclipseFile = getEclipsePath(); launch.setEnabled(eclipseFile.exists()); } }); browse = new Button(group, SWT.PUSH); browse.setText("Browse..."); browse.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false)); ((GridData)browse.getLayoutData()).widthHint = 80; browse.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { doBrowse(); } }); launch = new Button(group, SWT.PUSH); launch.setText("Launch"); launch.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false)); ((GridData)launch.getLayoutData()).widthHint = 80; launch.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { doLaunch(); } }); launch.setEnabled(getEclipsePath().exists()); launch.getShell().setDefaultButton(launch); } private void doLaunch() { if (launching == false) { File eclipseFile = getEclipsePath(); if (!eclipseFile.exists()) { showFileLocationErrorDialog(); return; } agent.resetOutput(); if (!configureINIFile(eclipseFile)) return; try { launch.setEnabled(false); launching = true; final Process process = Runtime.getRuntime().exec(eclipseFile.getAbsolutePath()); Thread readerThread = new Thread(new ReaderThread(process.getInputStream())); readerThread.start(); readerThread = new Thread(new ReaderThread(process.getErrorStream())); readerThread.start(); Thread terminationThread = new Thread(new Runnable() { @Override public void run() { try { process.waitFor(); } catch (InterruptedException e) { e.printStackTrace(); } Display.getDefault().asyncExec(new Runnable() { public void run() { processCompleted(); } }); } }); terminationThread.start(); } catch (IOException e1) { launch.setEnabled(getEclipsePath().exists()); launching = false; e1.printStackTrace(); } } } private File getEclipsePath() { File directory = new File(executablePath.getText()); File eclipseFile; if (Platform.getOS().equals(Platform.OS_WIN32)) eclipseFile = new File(directory, "eclipse.exe"); else eclipseFile = new File(directory, "eclipse"); return eclipseFile; } protected void processCompleted() { if (!launch.isDisposed()) launch.setEnabled(getEclipsePath().exists()); launching = false; writeINIFile(previousLines); } private boolean configureINIFile(File eclipseFile) { previousLines = readINIFile(); if (previousLines != null) { ArrayList<String> newContent = new ArrayList<String>(); String name = eclipseFile.getName(); for (String line : previousLines) { if (line.startsWith("-javaagent:")) continue; if (line.startsWith("-Xbootclasspath/a")) continue; if (line.startsWith("-Dcom.freescale.deadlockpreventer.")) continue; newContent.add(line); if (line.trim().equals("-vmargs")) { IProcess process = agent.createProcess(name); newContent.add(agent.getVMArg(process, IAgent.VM_ARG_AGENT)); newContent.add(agent.getVMArg(process, IAgent.VM_ARG_BOOT_CLASSPATH)); newContent.add(agent.getVMArg(process, IAgent.VM_ARG_BOOT_SERVER_PORT)); String additional = agent.getVMArg(process, IAgent.VM_ADDITIONAL_ARGUMENTS); if (additional != null) newContent.add(additional); } } return writeINIFile(newContent); } MessageDialog.openError(agent.getSite().getShell(), "Error", "Deadlock preventer activation failed: eclipse.ini not found."); return false; } private boolean writeINIFile(ArrayList<String> newContent) { File eclipseINIFile = new File(getEclipsePath().getParent(), "eclipse.ini"); if (eclipseINIFile.exists()) eclipseINIFile.delete(); FileOutputStream stream = null; try { String newLine = System.getProperty("line.separator"); stream = new FileOutputStream(eclipseINIFile); StringBuffer output = new StringBuffer(); for (String str : newContent) output.append(str + newLine); stream.write(output.toString().getBytes()); return true; } catch (FileNotFoundException e) { } catch (IOException e) { } finally { if (stream != null) { try { stream.close(); } catch (IOException e) { e.printStackTrace(); } } } return false; } private ArrayList<String> readINIFile() { File eclipseINIFile = new File(getEclipsePath().getParent(), "eclipse.ini"); try { FileReader reader = new FileReader(eclipseINIFile); try { ArrayList<String> content = new ArrayList<String>(); BufferedReader buf = new BufferedReader(reader); String line = buf.readLine(); while (line != null) { content.add(line); line = buf.readLine(); } return content; } catch (IOException e) { e.printStackTrace(); } finally { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } catch (FileNotFoundException e1) { e1.printStackTrace(); } return null; } private void doBrowse() { FileDialog dialog = new FileDialog (agent.getSite().getShell()); dialog.setText("Select the location of the eclipse.exe:"); String path = dialog.open(); if (path != null) { // massage the path File executable = new File(path); File directory; if (executable.exists()) directory = executable.getParentFile(); else { showFileLocationErrorDialog(); return; } executablePath.setText(directory.getAbsolutePath()); agent.setPref(IAgent.PREF_INSTALLATION_DIR, directory.getAbsolutePath()); } } private void showFileLocationErrorDialog() { MessageDialog.openError(agent.getSite().getShell(), "Invalid location", "The Eclipse installation directory must be selected (containing the 'eclipse' directory)."); } class ReaderThread implements Runnable { InputStream stream; public ReaderThread(InputStream inputStream) { stream = inputStream; } public void run() { BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); try { String line = reader.readLine(); while (line != null) { final String copy = line; Display.getDefault().asyncExec(new Runnable() { public void run() { agent.output("\n" + copy); } }); line = reader.readLine(); } } catch (IOException e) { e.printStackTrace(); } } } }