Skip to content

Commit

Permalink
Eclipse Launcher Updates
Browse files Browse the repository at this point in the history
- Store the password in secure storage
- Add a debug logger
- Lots of documentation updates
  • Loading branch information
jeffgbutler committed Aug 11, 2016
1 parent 20178e1 commit 1ba0ebf
Show file tree
Hide file tree
Showing 11 changed files with 303 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ <h2>MyBatis Generator Launch Configuration</h2>
with the normal Eclipse launch support. You can also add entries to the generator's
classpath through the same launch configuration support. This should make it easier to
access JDBC drivers, or to access your own generator plugins. </p>
<p>See the page <a href="usingTheLauncher.html">Using the Launcher</a> for more
information about using the launcher.</p>

<h2>Integrated Ant Task</h2>
<p>See the page <a href="usingAnt.html">Using the Integrated Ant Task</a> for more
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3c.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Using the Launcher</title>
<link type="text/css" rel="stylesheet" href="../mbgdoc/mbgstyle.css"/>
</head>
<body>
<h1>Using the Launcher</h1>
<p>The MyBatis Generator feature includes a custom launcher for
running MyBatis generator. The launcher leverages Eclipse's launch support
and enables you to create any number of custom launches. The launcher has far
more capability than the previous popup menu action. Further, the launch support
does not alter the Eclipse IDE classpath - which could happen inadvertently with
the prior popup menu action.</p>
<p>On this page we will cover some of the technical internals of the launcher.
We assume you are familiar with how the Eclipse launch support works in general.
If you are not familiar with Eclipse launching, just know that launch configurations
can be accessed with the Run&gt;Run Configurations... or Run&gt;Debug Configurations...
menu options.</p>

<h2>Launcher Internals</h2>
<p>Internally the launcher uses the MyBatis Generator Ant task to run the generator. The
launcher creates an Ant build script based on attributes in the launch
configuration and then uses Eclipse's Ant support to run the script.</p>
<p>The launch configuration allows you to specify a SQL script to run
before the generator is run. This can be useful when using in-memory databases
and is used during testing of the feature. Running a SQL script is accomplished
by using Ant's built in
SQL task to run a script you specify. See the Ant documentation for details
about the capabilities of the SQL task.</p>

<h2>Working with the Classpath</h2>
<p>The launcher allows you to add entries to the runtime classpath
of the launch. This can be used to add JDBC drivers to the classpath, and could
also be used to add Eclipse projects to the classpath. If you are developing a
plugin, you could add your plugin project to the classpath to test your plugin.</p>
<p>If you are developing a plugin, you do not need to add MyBatis Generator
itself to the launch classpath as it will already be added by the launcher.</p>
<p>Adding entries to the launcher classpath is generally preferable to using
a <code>&lt;classPathEntry&gt;</code> configuration element in the generator
configuration file. However, if you use a dependency JAR that relies on native code
(such as some DB2 drivers) it would be better to use the
<code>&lt;classPathEntry&gt;</code> configuration element. This because native
code can only be loaded by a single classloader and it is likely that
the generator classloader will be garbage collected before the launch classloader.</p>

<h2>What's Different in a Debug Launch?</h2>
<p>If you launch in debug mode, rather than run mode, the launcher will
launch Ant in debug mode and will log all messages to
a new Eclipse console called "MyBatis Generator". This can be useful when
using an SQL script as you will be able to see the script progress in the
console. You will also see many Ant configuration messages.</p>

<h2>How Passwords are Stored</h2>
<p>If you specify a password for connecting to a database with the Ant script, you
have options on how that password is stored.</p>
<p>If you select the check box specifying that
credentials should be stored in secure storage, then the user ID and password will
be stored in Eclipse's internal secure storage system. The password will be encrypted
using Eclipse's default support. The password will be in clear text in the generated Ant
script while the launch is running, but the generated Ant file will be deleted after the
launch completes.</p>
<p>If you do not select the check box specifying that
credentials should be stored in secure storage, then the user ID and password will
be stored in clear text in the Eclipse launch configuration. The password will also
be in clear text in the generated Ant script while the launch is running, and the
generated Ant file will not be deleted after the launch completes.</p>
<p>Launch configuration files are stored in<br/>
<code>&lt;workspace-directory&gt;/.metadata/.plugins/org.eclipse.debug.core/.launches</code>
</p>
<p>The generated Ant files are stored in<br/>
<code>&lt;workspace-directory&gt;/.metadata/.plugins/org.mybatis.generator.eclipse.ui/.generatedAntScripts</code>
</p>
</body>
</html>
2 changes: 2 additions & 0 deletions eclipse/org.mybatis.generator.eclipse.doc/toc_eclipseui.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
</topic>
<topic href="html/eclipseui/eclipseui.html" label="Using the Eclipse User Interface">
</topic>
<topic href="html/eclipseui/usingTheLauncher.html" label="Using the Launcher">
</topic>
<topic href="html/eclipseui/usingAnt.html" label="Using the Ant Task">
</topic>
<topic href="html/eclipseui/releasenotes.html" label="Release Notes">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.jdt.launching;bundle-version="3.8.0",
org.eclipse.jdt.debug.ui;bundle-version="3.7.101",
org.eclipse.core.expressions,
org.eclipse.core.variables;bundle-version="3.2.800"
org.eclipse.core.variables;bundle-version="3.2.800",
org.eclipse.equinox.security;bundle-version="1.2.100",
org.eclipse.ui.console;bundle-version="3.6.100"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Export-Package: org.mybatis.generator.eclipse.ui,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.mybatis.generator.eclipse.ui.ant;

import java.io.IOException;

import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildListener;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IOConsole;
import org.eclipse.ui.console.IOConsoleOutputStream;

public class DebugBuildListener implements BuildListener {
private IOConsole console = new IOConsole("MyBatis Generator", null); //$NON-NLS-1$
private IOConsoleOutputStream outputStream = console.newOutputStream();

public DebugBuildListener() {
ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] {console});
}

@Override
public void buildStarted(BuildEvent event) {
writeMessage("MyBatis Generator Started"); //$NON-NLS-1$
}

@Override
public void buildFinished(BuildEvent event) {
writeMessage("MyBatis Generator Finished"); //$NON-NLS-1$
}

@Override
public void targetStarted(BuildEvent event) {
writeMessage("Target " + event.getTarget().getName() + " - Started"); //$NON-NLS-1$ //$NON-NLS-2$
}

@Override
public void targetFinished(BuildEvent event) {
writeMessage("Target " + event.getTarget().getName() + " - Finished"); //$NON-NLS-1$ //$NON-NLS-2$
}

@Override
public void taskStarted(BuildEvent event) {
writeMessage("Task " + event.getTask().getTaskName() + " - Started"); //$NON-NLS-1$ //$NON-NLS-2$
}

@Override
public void taskFinished(BuildEvent event) {
writeMessage("Task " + event.getTask().getTaskName() + " - Finished"); //$NON-NLS-1$ //$NON-NLS-2$
}

@Override
public void messageLogged(BuildEvent event) {
writeMessage(" " + event.getMessage()); //$NON-NLS-1$
}

private void writeMessage(String message) {
try {
outputStream.write(message);
outputStream.write('\n');
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.eclipse.ui.launcher.tabs.LauncherUtils;
import org.mybatis.generator.internal.util.StringUtility;

/**
Expand Down Expand Up @@ -74,8 +75,8 @@ private void addSqlTaskIfNecessary(XmlElement parent) {

sqlTask.addAttribute(new Attribute("driver", getTextOrBlank(configuration, ATTR_SQL_SCRIPT_DRIVER_CLASS))); //$NON-NLS-1$
sqlTask.addAttribute(new Attribute("url", getTextOrBlank(configuration, ATTR_SQL_SCRIPT_CONNECTION_URL))); //$NON-NLS-1$
sqlTask.addAttribute(new Attribute("userid", getTextOrBlank(configuration, ATTR_SQL_SCRIPT_USERID))); //$NON-NLS-1$
sqlTask.addAttribute(new Attribute("password", getTextOrBlank(configuration, ATTR_SQL_SCRIPT_PASSWORD))); //$NON-NLS-1$
sqlTask.addAttribute(new Attribute("userid", LauncherUtils.getUserId(configuration))); //$NON-NLS-1$
sqlTask.addAttribute(new Attribute("password", LauncherUtils.getPassword(configuration))); //$NON-NLS-1$
sqlTask.addAttribute(new Attribute("src", sqlFileFullPath)); //$NON-NLS-1$

parent.addElement(sqlTask);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.ArrayList;
import java.util.List;

import org.apache.tools.ant.Project;
import org.eclipse.ant.core.AntCorePlugin;
import org.eclipse.ant.core.AntCorePreferences;
import org.eclipse.ant.core.AntRunner;
Expand All @@ -38,6 +39,7 @@
import org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate;
import org.mybatis.generator.eclipse.ui.Activator;
import org.mybatis.generator.eclipse.ui.Messages;
import org.mybatis.generator.eclipse.ui.launcher.tabs.LauncherUtils;

/**
* This launcher works by invoking the AntRunner on a generated ant script for the generator.
Expand All @@ -58,16 +60,28 @@ public void launch(ILaunchConfiguration configuration, String mode, ILaunch laun
throws CoreException {
AntRunner antRunner = new AntRunner();

String buildFile;
try {
antRunner.setBuildFileLocation(generateAntScript(configuration));
buildFile = generateAntScript(configuration);
} catch (IOException e) {
Status status = new Status(Status.ERROR, Activator.PLUGIN_ID, Messages.LAUNCH_ERROR_ERROR_GENERATING_ANT_FILE, e);
throw new CoreException(status);
}

antRunner.setBuildFileLocation(buildFile);
modifyAntClasspathIfNecessary(configuration, antRunner);
if ("debug".equals(mode)) { //$NON-NLS-1$
antRunner.setMessageOutputLevel(Project.MSG_DEBUG);
antRunner.setArguments("-debug"); //$NON-NLS-1$
antRunner.addBuildListener("org.mybatis.generator.eclipse.ui.ant.DebugBuildListener"); //$NON-NLS-1$
}

antRunner.run(monitor);

if (LauncherUtils.getBooleanOrFalse(configuration, GeneratorLaunchConstants.ATTR_SQL_SCRIPT_SECURE_CREDENTIALS)) {
File file = new File(buildFile);
file.delete();
}
}

private void modifyAntClasspathIfNecessary(ILaunchConfiguration configuration, AntRunner antRunner) throws CoreException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@
*/
package org.mybatis.generator.eclipse.ui.launcher;

import org.mybatis.generator.eclipse.ui.Activator;

public interface GeneratorLaunchConstants {
public static final String ATTR_CONFIGURATION_FILE_NAME = "MyBatis.Generator.ConfigTab.FileName"; //$NON-NLS-1$
public static final String ATTR_CONFIGURATION_FILE_NAME = Activator.PLUGIN_ID + ".CONFIG_TAB.FILE_NAME"; //$NON-NLS-1$

public static final String ATTR_SQL_SCRIPT_FILE_NAME = "MyBatis.Generator.SQLTab.ScriptFileName"; //$NON-NLS-1$
public static final String ATTR_SQL_SCRIPT_DRIVER_CLASS = "MyBatis.Generator.SQLTab.DriverClass"; //$NON-NLS-1$
public static final String ATTR_SQL_SCRIPT_CONNECTION_URL = "MyBatis.Generator.SQLTab.ConnectionURL"; //$NON-NLS-1$
public static final String ATTR_SQL_SCRIPT_USERID = "MyBatis.Generator.SQLTab.UserID"; //$NON-NLS-1$
public static final String ATTR_SQL_SCRIPT_PASSWORD = "MyBatis.Generator.SQLTab.Password"; //$NON-NLS-1$
public static final String ATTR_SQL_SCRIPT_FILE_NAME = Activator.PLUGIN_ID + ".SQL_TAB.FILE_NAME"; //$NON-NLS-1$
public static final String ATTR_SQL_SCRIPT_DRIVER_CLASS = Activator.PLUGIN_ID + ".SQL_TAB.DRIVER_CLASS"; //$NON-NLS-1$
public static final String ATTR_SQL_SCRIPT_CONNECTION_URL = Activator.PLUGIN_ID + ".SQL_TAB.CONNECTION_URL"; //$NON-NLS-1$
public static final String ATTR_SQL_SCRIPT_USERID = Activator.PLUGIN_ID + ".SQL_TAB.USER_ID"; //$NON-NLS-1$
public static final String ATTR_SQL_SCRIPT_PASSWORD = Activator.PLUGIN_ID + ".SQL_TAB.PASSWORD"; //$NON-NLS-1$
public static final String ATTR_SQL_SCRIPT_SECURE_CREDENTIALS = Activator.PLUGIN_ID + ".SQL_TAB.SECURE_CREDENTIALS"; //$NON-NLS-1$
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,16 @@
package org.mybatis.generator.eclipse.ui.launcher.tabs;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.equinox.security.storage.ISecurePreferences;
import org.eclipse.equinox.security.storage.SecurePreferencesFactory;
import org.eclipse.equinox.security.storage.StorageException;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Shell;
import org.mybatis.generator.eclipse.ui.Activator;
import org.mybatis.generator.eclipse.ui.launcher.GeneratorLaunchConstants;

public class LauncherUtils {

Expand All @@ -31,4 +40,94 @@ public static String getTextOrBlank(ILaunchConfiguration configuration, String a

return text;
}

public static String getTextOrBlank(ISecurePreferences node, String attribute) {
String text;

try {
text = node.get(attribute, ""); //$NON-NLS-1$
} catch (StorageException e) {
text = ""; //$NON-NLS-1$
}

return text;
}

public static boolean getBooleanOrFalse(ILaunchConfiguration configuration, String attribute) {
boolean answer;

try {
answer = configuration.getAttribute(attribute, false);
} catch (CoreException e) {
answer = false;
}

return answer;
}

public static void setPassword(ILaunchConfigurationWorkingCopy configuration, String password, Shell shell) {
boolean secure = getBooleanOrFalse(configuration, GeneratorLaunchConstants.ATTR_SQL_SCRIPT_SECURE_CREDENTIALS);
if (secure) {
ISecurePreferences node = getSecurePreferencesNode();
try {
node.put("password", password, true); //$NON-NLS-1$
} catch (StorageException e) {
logException(shell, e);
}
} else {
configuration.setAttribute(GeneratorLaunchConstants.ATTR_SQL_SCRIPT_PASSWORD, password);
}
}

public static String getPassword(ILaunchConfiguration configuration) {
boolean secure = getBooleanOrFalse(configuration, GeneratorLaunchConstants.ATTR_SQL_SCRIPT_SECURE_CREDENTIALS);
String password;
if (secure) {
ISecurePreferences node = getSecurePreferencesNode();
password = getTextOrBlank(node, "password"); //$NON-NLS-1$
} else {
password = getTextOrBlank(configuration, GeneratorLaunchConstants.ATTR_SQL_SCRIPT_PASSWORD);
}
return password;
}

public static void setUserId(ILaunchConfigurationWorkingCopy configuration, String userId, Shell shell) {
boolean secure = getBooleanOrFalse(configuration, GeneratorLaunchConstants.ATTR_SQL_SCRIPT_SECURE_CREDENTIALS);
if (secure) {
ISecurePreferences node = getSecurePreferencesNode();
try {
node.put("user", userId, false); //$NON-NLS-1$
} catch (StorageException e) {
logException(shell, e);
}
} else {
configuration.setAttribute(GeneratorLaunchConstants.ATTR_SQL_SCRIPT_USERID, userId);
}
}

public static String getUserId(ILaunchConfiguration configuration) {
boolean secure = getBooleanOrFalse(configuration, GeneratorLaunchConstants.ATTR_SQL_SCRIPT_SECURE_CREDENTIALS);
String userId;
if (secure) {
ISecurePreferences node = getSecurePreferencesNode();
userId = getTextOrBlank(node, "user"); //$NON-NLS-1$
} else {
userId = getTextOrBlank(configuration, GeneratorLaunchConstants.ATTR_SQL_SCRIPT_USERID);
}
return userId;
}

private static void logException(Shell shell, StorageException e) {
MessageDialog.openError(shell,
"Secure Storage Error",
"Error writing to secure storage. See error log for more details.");
Status status = new Status(Status.ERROR, Activator.PLUGIN_ID, "Error writing to secure storage", e);
Activator.getDefault().getLog().log(status);
}

private static ISecurePreferences getSecurePreferencesNode() {
ISecurePreferences root = SecurePreferencesFactory.getDefault();
ISecurePreferences node = root.node("/org.mybatis.generator/sqlscript"); //$NON-NLS-1$
return node;
}
}
Loading

0 comments on commit 1ba0ebf

Please sign in to comment.