| /******************************************************************************* |
| * Copyright (c) 2008 Oracle. 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: |
| * Oracle - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jpt.eclipselink.core.internal.ddlgen; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Properties; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.ILaunch; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.debug.core.ILaunchConfigurationType; |
| import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; |
| import org.eclipse.debug.core.ILaunchManager; |
| import org.eclipse.debug.core.ILaunchesListener2; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; |
| import org.eclipse.jdt.launching.IRuntimeClasspathEntry; |
| import org.eclipse.jdt.launching.IVMInstall; |
| import org.eclipse.jdt.launching.JavaRuntime; |
| import org.eclipse.jpt.core.JpaPlatform; |
| import org.eclipse.jpt.core.JpaProject; |
| import org.eclipse.jpt.core.internal.validation.JpaHelper; |
| import org.eclipse.jpt.core.internal.validation.JpaValidator; |
| import org.eclipse.jpt.db.ConnectionProfile; |
| import org.eclipse.jpt.eclipselink.core.internal.context.connection.Connection; |
| import org.eclipse.jpt.eclipselink.core.internal.context.customization.Customization; |
| import org.eclipse.jpt.eclipselink.core.internal.context.logging.Logging; |
| import org.eclipse.jpt.eclipselink.core.internal.context.logging.LoggingLevel; |
| import org.eclipse.jpt.eclipselink.core.internal.context.schema.generation.DdlGenerationType; |
| import org.eclipse.jpt.eclipselink.core.internal.context.schema.generation.OutputMode; |
| import org.eclipse.jpt.eclipselink.core.internal.context.schema.generation.SchemaGeneration; |
| import org.eclipse.wst.validation.internal.operations.ValidatorJob; |
| |
| /** |
| * EclipseLinkDLLGenerator launches the EclipseLink DDL generator in a separate VM. |
| * For this it will create a Java Configuration named "EclipseLink" |
| * in the target workspace (note: the configuration will be overridden at each run). |
| * It will than launch the configuration created with the login information from |
| * the current Dali project, and passes it to EclipseLink. |
| * |
| * Pre-req: |
| * org.eclipse.jpt.eclipselink.core.ddlgen.jar in ECLIPSE_HOME/plugins |
| */ |
| public class EclipseLinkDDLGenerator |
| { |
| static public String ECLIPSELINK_DDL_GEN_JAR_VERSION = "1.0.0"; //$NON-NLS-1$ |
| static public String LAUNCH_CONFIG_NAME = "EclipseLink"; //$NON-NLS-1$ |
| static public String DDL_GEN_PACKAGE_NAME = "org.eclipse.jpt.eclipselink.core.ddlgen"; //$NON-NLS-1$ |
| static public String ECLIPSELINK_DDL_GEN_CLASS = DDL_GEN_PACKAGE_NAME + ".Main"; //$NON-NLS-1$ |
| static public String ECLIPSELINK_DDL_GEN_JAR = DDL_GEN_PACKAGE_NAME + "_" + ECLIPSELINK_DDL_GEN_JAR_VERSION + ".jar"; //$NON-NLS-1$ |
| static public String PROPERTIES_FILE_NAME = "login.properties"; //$NON-NLS-1$ |
| static public String ECLIPSE_HOME = "ECLIPSE_HOME"; //$NON-NLS-1$ |
| static public String PLUGINS_DIR = "plugins"; //$NON-NLS-1$ |
| private IVMInstall jre; |
| private ILaunchConfigurationWorkingCopy launchConfig; |
| private ILaunch launch; |
| |
| private String puName; |
| private JpaProject project; |
| private String projectLocation; |
| private boolean isDebug = false; |
| |
| // ********** constructors ********** |
| |
| public static void generate(String puName, JpaProject project, String projectLocation, IProgressMonitor monitor) { |
| if (puName == null || puName.length() == 0 || project == null) { |
| throw new NullPointerException(); |
| } |
| new EclipseLinkDDLGenerator(puName, project, projectLocation, monitor).generate(); |
| } |
| |
| private EclipseLinkDDLGenerator(String puName, JpaProject project, String projectLocation, IProgressMonitor monitor) { |
| super(); |
| this.puName = puName; |
| this.project = project; |
| this.projectLocation = projectLocation; |
| this.initialize(); |
| } |
| |
| // ********** Queries ********** |
| |
| protected JpaPlatform getPlatform() { |
| return this.project.getJpaPlatform(); |
| } |
| |
| protected ConnectionProfile getConnectionProfile() { |
| return this.project.getConnectionProfile(); |
| } |
| |
| protected ILaunch getLaunch() { |
| return this.launch; |
| } |
| |
| protected ILaunchManager getLaunchManager() { |
| return DebugPlugin.getDefault().getLaunchManager(); |
| } |
| |
| private IVMInstall getProjectJRE() throws CoreException { |
| |
| return JavaRuntime.getVMInstall(this.project.getJavaProject()); |
| } |
| |
| // ********** behavior ********** |
| |
| protected void initialize() { |
| try { |
| this.jre = this.getProjectJRE(); |
| if(this.jre == null) { |
| String message = "Could not identify the VM."; |
| throw new RuntimeException(message); |
| } |
| this.launchConfig = this.buildLaunchConfiguration(); |
| } |
| catch (CoreException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| protected void generate() { |
| this.preGenerate(); |
| String propertiesFile = this.projectLocation + "/" + PROPERTIES_FILE_NAME; |
| try { |
| this.initializeLaunchConfiguration(this.projectLocation, propertiesFile); |
| |
| this.saveLoginProperties(this.projectLocation, propertiesFile); |
| |
| this.launch = this.saveAndLaunchConfig(); |
| this.addLaunchListener(); |
| } |
| catch (CoreException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| private void initializeLaunchConfiguration(String projectLocation, String propertiesFile) throws CoreException { |
| |
| this.specifyJRE(this.jre.getName(), this.jre.getVMInstallType().getId()); |
| |
| this.specifyProject(this.project.getProject().getName()); |
| this.specifyMainType(ECLIPSELINK_DDL_GEN_CLASS); |
| |
| this.specifyProgramArguments(this.puName, propertiesFile); |
| this.specifyWorkingDir(projectLocation); |
| |
| this.specifyClasspathProperties(this.project, this.buildJdbcJarPath(), this.buildBootstrapJarPath()); |
| } |
| |
| private void addLaunchListener() { |
| |
| this.getLaunchManager().addLaunchListener(this.buildLaunchListener()); |
| } |
| |
| protected void preGenerate() { |
| this.project.getConnectionProfile().disconnect(); |
| } |
| |
| protected void postGenerate() { |
| try { |
| if(! this.isDebug) { |
| this.removeLaunchConfiguration(LAUNCH_CONFIG_NAME); |
| } |
| } |
| catch ( CoreException e) { |
| throw new RuntimeException(e); |
| } |
| this.project.getConnectionProfile().connect(); |
| |
| this.validateProject(); |
| } |
| |
| protected void validateProject() { |
| JpaValidator validator = new JpaValidator(); |
| IProject project = this.project.getProject(); |
| JpaHelper helper = new JpaHelper(); |
| helper.setProject(project); |
| |
| ValidatorJob validatorJob = new ValidatorJob(validator, "JPA Validator", "", project, helper); |
| validatorJob.setRule(ResourcesPlugin.getWorkspace().getRoot()); |
| validatorJob.setUser(true); |
| validatorJob.schedule(); |
| } |
| |
| private IPath buildJdbcJarPath() { |
| return new Path(this.project.getConnectionProfile().getDriverJarList()); |
| } |
| |
| private IPath buildBootstrapJarPath() { |
| IPath path = JavaCore.getClasspathVariable(ECLIPSE_HOME); |
| return path.append(PLUGINS_DIR).append(ECLIPSELINK_DDL_GEN_JAR); |
| } |
| |
| private ILaunchesListener2 buildLaunchListener() { |
| return new ILaunchesListener2() { |
| |
| public void launchesTerminated(ILaunch[] launches) { |
| for (int i = 0; i < launches.length; i++) { |
| ILaunch launch = launches[i]; |
| if (launch.equals(EclipseLinkDDLGenerator.this.getLaunch())) { |
| |
| EclipseLinkDDLGenerator.this.postGenerate(); |
| return; |
| } |
| } |
| } |
| |
| public void launchesAdded(ILaunch[] launches) { |
| // not interested to this event |
| } |
| |
| public void launchesChanged(ILaunch[] launches) { |
| // not interested to this event |
| } |
| |
| public void launchesRemoved(ILaunch[] launches) { |
| // not interested to this event |
| } |
| }; |
| } |
| |
| // ********** launch configuration ********** |
| |
| private void specifyJRE(String jreName, String vmId) { |
| |
| this.launchConfig.setAttribute(IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, jreName); |
| this.launchConfig.setAttribute(IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, vmId); |
| } |
| |
| private void specifyProject(String projectName) { |
| |
| this.launchConfig.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, projectName); |
| } |
| |
| private void specifyMainType(String mainType) { |
| |
| this.launchConfig.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, mainType); |
| } |
| |
| private void specifyProgramArguments(String puName, String propertiesPath) { |
| |
| StringBuffer programArguments = new StringBuffer(); |
| programArguments.append(this.buildPuNameArgument(puName)); |
| programArguments.append(this.buildPropertiesPathArgument(propertiesPath)); |
| programArguments.append(this.buildDebugArgument()); |
| |
| this.launchConfig.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, programArguments.toString()); |
| } |
| |
| private void specifyClasspathProperties(JpaProject project, IPath jdbcJar, IPath bootstrapJar) throws CoreException { |
| // DDL_GEN jar |
| IRuntimeClasspathEntry bootstrapEntry = JavaRuntime.newArchiveRuntimeClasspathEntry(bootstrapJar); |
| bootstrapEntry.setClasspathProperty(IRuntimeClasspathEntry.USER_CLASSES); |
| // Default Project classpath |
| IRuntimeClasspathEntry defaultEntry = JavaRuntime.newDefaultProjectClasspathEntry(project.getJavaProject()); |
| defaultEntry.setClasspathProperty(IRuntimeClasspathEntry.USER_CLASSES); |
| // JDBC jar |
| IRuntimeClasspathEntry jdbcEntry = JavaRuntime.newArchiveRuntimeClasspathEntry(jdbcJar); |
| jdbcEntry.setClasspathProperty(IRuntimeClasspathEntry.USER_CLASSES); |
| // System Library |
| IPath systemLibsPath = new Path(JavaRuntime.JRE_CONTAINER); |
| IRuntimeClasspathEntry systemLibsEntry = JavaRuntime.newRuntimeContainerClasspathEntry(systemLibsPath, IRuntimeClasspathEntry.STANDARD_CLASSES); |
| |
| List<String> classpath = new ArrayList<String>(); |
| classpath.add(bootstrapEntry.getMemento()); |
| classpath.add(defaultEntry.getMemento()); |
| classpath.add(jdbcEntry.getMemento()); |
| classpath.add(systemLibsEntry.getMemento()); |
| |
| this.launchConfig.setAttribute(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH, classpath); |
| this.launchConfig.setAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH, false); |
| } |
| |
| private void specifyWorkingDir(String projectLocation) { |
| |
| File workingDir = new Path(projectLocation).toFile(); |
| this.launchConfig.setAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, workingDir.getAbsolutePath()); |
| } |
| |
| private ILaunch saveAndLaunchConfig() throws CoreException { |
| ILaunchConfiguration configuration = this.launchConfig.doSave(); |
| |
| return configuration.launch(ILaunchManager.RUN_MODE, new NullProgressMonitor()); |
| } |
| |
| private ILaunchConfigurationWorkingCopy buildLaunchConfiguration() throws CoreException { |
| ILaunchConfigurationWorkingCopy launchConfig = null; |
| this.removeLaunchConfiguration( LAUNCH_CONFIG_NAME); |
| |
| ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); |
| ILaunchConfigurationType type = manager.getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION); |
| |
| launchConfig = type.newInstance(null, LAUNCH_CONFIG_NAME); |
| return launchConfig; |
| } |
| |
| private void removeLaunchConfiguration(String launchConfigurationName) throws CoreException { |
| |
| ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); |
| ILaunchConfigurationType type = manager.getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION); |
| |
| ILaunchConfiguration[] configurations = manager.getLaunchConfigurations(type); |
| for (int i = 0; i < configurations.length; i++) { |
| ILaunchConfiguration configuration = configurations[i]; |
| if (configuration.getName().equals(launchConfigurationName)) { |
| configuration.delete(); |
| break; |
| } |
| } |
| } |
| |
| // ********** EclipseLink properties ********** |
| |
| private void buildProjectLocationProperty(Properties properties, String location) { |
| this.putProperty(properties, |
| SchemaGeneration.ECLIPSELINK_APPLICATION_LOCATION, |
| location); |
| } |
| |
| private void buildDDLModeProperties(Properties properties) { |
| this.putProperty(properties, |
| SchemaGeneration.ECLIPSELINK_DDL_GENERATION_TYPE, |
| DdlGenerationType.DROP_AND_CREATE_TABLES); |
| this.putProperty(properties, |
| SchemaGeneration.ECLIPSELINK_DDL_GENERATION_OUTPUT_MODE, |
| OutputMode.DATABASE); |
| } |
| |
| private void buildLoginProperties(Properties properties) { |
| ConnectionProfile profile = this.getConnectionProfile(); |
| |
| this.putProperty(properties, |
| Connection.ECLIPSELINK_BIND_PARAMETERS, |
| "false"); |
| this.putProperty(properties, |
| Connection.ECLIPSELINK_DRIVER, |
| profile.getDriverClassName()); |
| this.putProperty(properties, |
| Connection.ECLIPSELINK_URL, |
| profile.getUrl()); |
| this.putProperty(properties, |
| Connection.ECLIPSELINK_USER, |
| profile.getUserName()); |
| this.putProperty(properties, |
| Connection.ECLIPSELINK_PASSWORD, |
| profile.getUserPassword()); |
| this.putProperty(properties, |
| Logging.ECLIPSELINK_LEVEL, |
| LoggingLevel.FINEST); |
| this.putProperty(properties, |
| Logging.ECLIPSELINK_TIMESTAMP, |
| "false"); |
| this.putProperty(properties, |
| Logging.ECLIPSELINK_THREAD, |
| "false"); |
| this.putProperty(properties, |
| Logging.ECLIPSELINK_SESSION, |
| "false"); |
| this.putProperty(properties, |
| Logging.ECLIPSELINK_EXCEPTIONS, |
| "true"); |
| this.putProperty(properties, |
| Customization.ECLIPSELINK_THROW_EXCEPTIONS, |
| "true"); |
| } |
| |
| private void putProperty(Properties properties, String key, String value) { |
| properties.put(key, (value == null) ? "" : value); |
| } |
| |
| private void saveLoginProperties(String projectLocation, String propertiesFile) { |
| Properties elProperties = new Properties(); |
| |
| this.buildLoginProperties(elProperties); |
| |
| this.buildDDLModeProperties(elProperties); |
| |
| this.buildProjectLocationProperty(elProperties, projectLocation); |
| try { |
| File file = new File(propertiesFile); |
| file.createNewFile(); |
| FileOutputStream stream = new FileOutputStream(file); |
| elProperties.store(stream, null); |
| stream.close(); |
| } |
| catch (Exception e) { |
| String message = "Error saving: " + propertiesFile; |
| throw new RuntimeException(message, e); |
| } |
| } |
| |
| // ********** Main arguments ********** |
| |
| private String buildPuNameArgument(String puName) { |
| return " -pu \"" + puName + "\""; |
| } |
| |
| private String buildPropertiesPathArgument(String propertiesFile) { |
| return " -p \"" + propertiesFile + "\""; |
| } |
| |
| private String buildDebugArgument() { |
| return (this.isDebug) ? " -debug" : ""; |
| } |
| } |