| /******************************************************************************* |
| * Copyright (c) 2010 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.jaxb.core.internal; |
| |
| import java.io.BufferedReader; |
| import java.io.ByteArrayInputStream; |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.io.UnsupportedEncodingException; |
| import java.util.ArrayList; |
| import java.util.List; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.FileLocator; |
| 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.core.runtime.Platform; |
| import org.eclipse.core.runtime.SubMonitor; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IPackageFragment; |
| import org.eclipse.jdt.core.IPackageFragmentRoot; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; |
| import org.eclipse.jdt.launching.IRuntimeClasspathEntry; |
| import org.eclipse.jpt.core.internal.gen.AbstractJptGenerator; |
| import org.eclipse.jpt.core.internal.utility.jdt.JDTTools; |
| import org.eclipse.jpt.jaxb.ui.JptJaxbUiPlugin; |
| import org.eclipse.osgi.service.datalocation.Location; |
| import org.osgi.framework.Bundle; |
| |
| /** |
| * SchemaGenerator |
| */ |
| public class SchemaGenerator extends AbstractJptGenerator |
| { |
| static public String LAUNCH_CONFIG_NAME = "JAXB Schema Gen Run Config"; //$NON-NLS-1$ |
| static public String JAXB_SCHEMA_GEN_PACKAGE_NAME = "org.eclipse.jpt.jaxb.core.schemagen"; //$NON-NLS-1$ |
| static public String JAXB_SCHEMA_GEN_CLASS = JAXB_SCHEMA_GEN_PACKAGE_NAME + ".Main"; //$NON-NLS-1$ |
| static public String ECLIPSELINK_JAXB_SCHEMA_GEN_PACKAGE_NAME = "org.eclipse.jpt.jaxb.eclipselink.core.schemagen"; //$NON-NLS-1$ |
| static public String ECLIPSELINK_JAXB_SCHEMA_GEN_CLASS = ECLIPSELINK_JAXB_SCHEMA_GEN_PACKAGE_NAME + ".Main"; //$NON-NLS-1$ |
| |
| static public String ECLIPSELINK_JAXB_CONTEXT_FACTORY = "org.eclipse.persistence.jaxb.JAXBContextFactory"; //$NON-NLS-1$ |
| static public String ECLIPSELINK_JAXB_PROPERTIES_FILE_CONTENTS = "javax.xml.bind.context.factory=" + ECLIPSELINK_JAXB_CONTEXT_FACTORY; //$NON-NLS-1$ |
| static public String JAXB_PROPERTIES_FILE_NAME = "jaxb.properties"; //$NON-NLS-1$ |
| |
| static public String JAXB_SCHEMA_GEN_JAR = JAXB_SCHEMA_GEN_PACKAGE_NAME + "_"; //$NON-NLS-1$ |
| static public String ECLIPSELINK_JAXB_SCHEMA_GEN_JAR = ECLIPSELINK_JAXB_SCHEMA_GEN_PACKAGE_NAME + "_"; //$NON-NLS-1$ |
| |
| static public String JAXB_GENERIC_SCHEMA_GEN_CLASS = "javax.xml.bind.JAXBContext"; //$NON-NLS-1$ |
| static public String JAXB_ECLIPSELINK_SCHEMA_GEN_CLASS = "org.eclipse.persistence.jaxb.JAXBContext"; //$NON-NLS-1$ |
| static public String PLUGINS_DIR = "plugins/"; //$NON-NLS-1$ |
| |
| private final String targetSchemaName; |
| private final String[] sourceClassNames; |
| private String mainType; |
| private boolean useMoxy; |
| |
| // ********** static methods ********** |
| |
| public static void generate( |
| IJavaProject javaProject, |
| String targetSchemaName, |
| String[] sourceClassNames, |
| boolean useMoxy, |
| IProgressMonitor monitor) { |
| if (javaProject == null) { |
| throw new NullPointerException(); |
| } |
| new SchemaGenerator(javaProject, |
| targetSchemaName, |
| sourceClassNames, |
| useMoxy).generate(monitor); |
| } |
| |
| // ********** constructors ********** |
| |
| protected SchemaGenerator( |
| IJavaProject javaProject, |
| String targetSchemaName, |
| String[] sourceClassNames, |
| boolean useMoxy) { |
| super(javaProject); |
| this.targetSchemaName = targetSchemaName; |
| this.sourceClassNames = sourceClassNames; |
| this.useMoxy = useMoxy; |
| this.mainType = (this.useMoxy) ? |
| ECLIPSELINK_JAXB_SCHEMA_GEN_CLASS : |
| JAXB_SCHEMA_GEN_CLASS; |
| this.initialize(); |
| } |
| |
| @Override |
| protected String getMainType() { |
| return this.mainType; |
| } |
| |
| @Override |
| protected String getLaunchConfigName() { |
| return LAUNCH_CONFIG_NAME; |
| } |
| |
| |
| // ********** behavior ********** |
| |
| @Override |
| protected void preGenerate(IProgressMonitor monitor) { |
| // generate jaxb.properties file if necessary |
| if (this.useMoxy){ |
| if (!isJaxbPropertiesFilePresent()){ |
| this.generateJaxbPropertiesFile(monitor); |
| } |
| else if (!isJaxbContextMoxy()){ |
| //properties file actually specifies a different implementation |
| //override wizard setting and fall back to generic generation |
| this.useMoxy = false; |
| this.mainType = JAXB_SCHEMA_GEN_CLASS; |
| } |
| } |
| } |
| |
| @Override |
| protected void postGenerate() { |
| super.postGenerate(); |
| try { |
| this.getProject().refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); |
| } |
| catch (CoreException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| /** |
| * Returns the first "jaxb.properties" file that is found in a valid source |
| * folder in the project. |
| * |
| * Returns null if no "jaxb.properties" file is found. |
| */ |
| private IFile getJaxbPropertiesFile() { |
| return getJaxbPropertiesFileFromPackageRoots(JDTTools.getJavaSourceFolders(this.javaProject)); |
| } |
| |
| private IFile getJaxbPropertiesFileFromPackageRoots(Iterable<IPackageFragmentRoot> packageFragmentRoots){ |
| Object[] objects = null; |
| IJavaElement[] javaElements; |
| try { |
| for (IPackageFragmentRoot pfr : packageFragmentRoots) { |
| javaElements = pfr.getChildren(); |
| for (IJavaElement javaElement : javaElements) { |
| objects = ((IPackageFragment) javaElement).getNonJavaResources(); |
| for (Object object : objects) { |
| IResource resource = (IResource) object; |
| if (resource.getName().equals(JAXB_PROPERTIES_FILE_NAME)) { |
| // jaxb.properties has been found |
| return (IFile)resource; |
| } |
| } |
| } |
| } |
| } catch (JavaModelException jme) { |
| throw new RuntimeException(jme); |
| } |
| return null; |
| } |
| |
| private boolean isJaxbPropertiesFilePresent(){ |
| return getJaxbPropertiesFile()!= null; |
| } |
| |
| private boolean isJaxbContextMoxy(){ |
| |
| InputStream in = null; |
| try { |
| in = getJaxbPropertiesFile().getContents(); |
| BufferedReader reader = new BufferedReader(new InputStreamReader(in)); |
| String line = reader.readLine(); |
| //jaxb.properties will only contain one property entry, the JAXBContextFactory |
| String propertyValue = line.substring(line.indexOf("=") + 1); //$NON-NLS-1$ |
| if (propertyValue.equals(ECLIPSELINK_JAXB_CONTEXT_FACTORY)){ |
| return true; |
| } |
| } catch (CoreException ce){ |
| throw new RuntimeException(ce); |
| } catch (IOException ioe){ |
| throw new RuntimeException(ioe); |
| } finally { |
| if (in != null){ |
| try{ |
| in.close(); |
| } catch (IOException ioe) { |
| throw new RuntimeException(ioe); |
| } |
| } |
| } |
| return false; |
| } |
| |
| private void generateJaxbPropertiesFile(IProgressMonitor monitor) { |
| SubMonitor sm = SubMonitor.convert(monitor, 1); |
| sm.subTask(JptJaxbCoreMessages.SchemaGenerator_creatingJAXBPropertiesFileTask); |
| |
| IPackageFragment packageFragment = findPackageFragementForSourceClassName(this.sourceClassNames[0]); |
| |
| IFolder folder = (IFolder)packageFragment.getResource(); |
| IFile file = folder.getFile(JAXB_PROPERTIES_FILE_NAME); |
| |
| byte[] bytes; |
| try { |
| bytes = ECLIPSELINK_JAXB_PROPERTIES_FILE_CONTENTS.getBytes("UTF-8"); //$NON-NLS-1$ |
| } catch (UnsupportedEncodingException e) { |
| throw new RuntimeException(e); |
| } |
| |
| InputStream contents = new ByteArrayInputStream(bytes); |
| |
| try { |
| //the input stream will be closed as a result of calling create |
| file.create(contents, IResource.NONE, sm.newChild(1)); |
| } catch (CoreException ce) { |
| throw new RuntimeException(ce); |
| } |
| } |
| |
| private IPackageFragment findPackageFragementForSourceClassName(String sourceClassName) { |
| String packageName = sourceClassName.substring(0, sourceClassName.lastIndexOf('.')); |
| |
| //Find the existing package fragment where we want to generate |
| for (IPackageFragmentRoot pfr : JDTTools.getJavaSourceFolders(this.javaProject)) { |
| //use the package of the first source class as the package for generation |
| IPackageFragment packageFragment = pfr.getPackageFragment(packageName); |
| if (packageFragment.exists()){ |
| return packageFragment; |
| } |
| } |
| //the existing package fragment was not found |
| throw new IllegalStateException("Java package must exist for source class"); |
| } |
| |
| |
| // ********** Launch Configuration Setup ********** |
| |
| @Override |
| protected List<String> buildClasspath() throws CoreException { |
| List<String> classpath = new ArrayList<String>(); |
| // Schema_Gen jar |
| classpath.add(getBootstrapJarClasspathEntry().getMemento()); |
| // Default Project classpath |
| classpath.add(this.getDefaultProjectClasspathEntry().getMemento()); |
| // System Library |
| classpath.add(this.getSystemLibraryClasspathEntry().getMemento()); |
| return classpath; |
| } |
| |
| @Override |
| protected void specifyProgramArguments() { |
| |
| StringBuffer programArguments = new StringBuffer(); |
| // sourceClassNames |
| this.appendClassNameArguments(programArguments); |
| |
| // schema |
| programArguments.append(" -s \""); //$NON-NLS-1$ |
| programArguments.append(this.targetSchemaName); |
| programArguments.append('"'); |
| |
| this.launchConfig.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, programArguments.toString()); |
| } |
| |
| private void appendClassNameArguments(StringBuffer sb) { |
| for (String className : this.sourceClassNames) { |
| sb.append(" -c "); //$NON-NLS-1$ |
| sb.append(className); |
| } |
| } |
| |
| |
| // ********** private methods ********** |
| |
| private IRuntimeClasspathEntry getBootstrapJarClasspathEntry() { |
| return getArchiveClasspathEntry(this.buildBootstrapJarPath()); |
| } |
| |
| private IPath buildBootstrapJarPath() { |
| String jarName = (this.useMoxy) ? |
| ECLIPSELINK_JAXB_SCHEMA_GEN_JAR : |
| JAXB_SCHEMA_GEN_JAR; |
| |
| try { |
| File jarInstallDir = this.getBundleParentDir(JptJaxbUiPlugin.PLUGIN_ID); |
| |
| List<File> result = new ArrayList<File>(); |
| this.findFile(jarName, jarInstallDir, result); |
| if (result.isEmpty()) { |
| throw new RuntimeException("Could not find: " + jarName + "#.#.#v###.jar in: " + jarInstallDir); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| File ddlGenJarFile = result.get(0); |
| String ddlGenJarPath = ddlGenJarFile.getCanonicalPath(); |
| return new Path(ddlGenJarPath); |
| } |
| catch (IOException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| private void findFile(String fileName, File directory, List<? super File> list) { |
| if(directory.listFiles() == null) { |
| throw new RuntimeException("Could not find directory: " + directory); //$NON-NLS-1$ |
| } |
| for (File file : directory.listFiles()) { |
| if (file.getName().startsWith(fileName)) { |
| list.add(file); |
| } |
| if (file.isDirectory()) { |
| this.findFile(fileName, file, list); |
| } |
| } |
| } |
| |
| private File getBundleParentDir(String bundleName) throws IOException { |
| |
| if (Platform.inDevelopmentMode()) { |
| Location eclipseHomeLoc = Platform.getInstallLocation(); |
| String eclipseHome = eclipseHomeLoc.getURL().getPath(); |
| if ( ! eclipseHome.endsWith(PLUGINS_DIR)) { |
| eclipseHome += PLUGINS_DIR; |
| } |
| return new File(eclipseHome); |
| } |
| Bundle bundle = Platform.getBundle(bundleName); |
| return FileLocator.getBundleFile(bundle).getParentFile(); |
| } |
| } |