/******************************************************************************* | |
* Copyright (c) 2009 by SAP AG, Walldorf. | |
* 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: | |
* SAP AG - initial API and implementation | |
*******************************************************************************/ | |
package org.eclipse.jst.ws.jaxws.testutils.project; | |
import java.io.IOException; | |
import java.net.MalformedURLException; | |
import java.net.URL; | |
import java.util.HashMap; | |
import java.util.Map; | |
import org.eclipse.core.internal.resources.ResourceException; | |
import org.eclipse.core.resources.IContainer; | |
import org.eclipse.core.resources.IFolder; | |
import org.eclipse.core.resources.IProject; | |
import org.eclipse.core.resources.IProjectDescription; | |
import org.eclipse.core.resources.IResource; | |
import org.eclipse.core.resources.IWorkspaceRoot; | |
import org.eclipse.core.resources.ResourcesPlugin; | |
import org.eclipse.core.runtime.CoreException; | |
import org.eclipse.core.runtime.FileLocator; | |
import org.eclipse.core.runtime.IPath; | |
import org.eclipse.core.runtime.NullProgressMonitor; | |
import org.eclipse.core.runtime.Path; | |
import org.eclipse.core.runtime.Platform; | |
import org.eclipse.core.runtime.Status; | |
import org.eclipse.jdt.core.IClasspathEntry; | |
import org.eclipse.jdt.core.ICompilationUnit; | |
import org.eclipse.jdt.core.IJavaProject; | |
import org.eclipse.jdt.core.IPackageFragment; | |
import org.eclipse.jdt.core.IPackageFragmentRoot; | |
import org.eclipse.jdt.core.IType; | |
import org.eclipse.jdt.core.JavaCore; | |
import org.eclipse.jdt.core.JavaModelException; | |
import org.eclipse.jdt.launching.JavaRuntime; | |
import org.eclipse.jst.ws.jaxws.testutils.jobs.JobUtils; | |
import org.eclipse.jst.ws.jaxws.utils.ContractChecker; | |
import org.osgi.framework.Bundle; | |
@SuppressWarnings("restriction") | |
public class TestProject | |
{ | |
public final static char CLASS_SEPARATOR = '#'; | |
private int idInMillis = 0; | |
private IProject project; | |
private IJavaProject javaProject; | |
private IPackageFragmentRoot sourceFolder; | |
public TestProject() throws CoreException | |
{ | |
this(""); | |
} | |
public TestProject(String name) throws CoreException | |
{ | |
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); | |
/* | |
* Calculate the name of the test project. The formula: JavaProj_ + <current_time_in_millis? + <idInMillis> is ussed. In this formula | |
* JavaProj_ is a string litteral, current_time_in_millis is obvious. idInMillis is an integer incremented each time a project name is | |
* calculated. This is necessary because the system timer has precision about 10 ms. Thus it's possible that two consecutive project creations | |
* give the same project name. For example the project is creted then the test executes very fast and a new project is created again. In the | |
* same time simply the id is not enough as a different test run might produce the same project name. Thus the combination tim_millis + | |
* idInMillis gives a unique project name | |
*/ | |
final String testProjectName = "JavaProj_" + Long.toString(System.currentTimeMillis()) + "_" + idInMillis++ + name; | |
project = root.getProject(testProjectName); | |
project.create(null); | |
project.open(null); | |
configureJavaProject(); | |
} | |
private void configureJavaProject() throws CoreException | |
{ | |
javaProject = JavaCore.create(project); | |
IFolder binFolder = createBinFolder(); | |
setJavaNature(); | |
javaProject.setRawClasspath(new IClasspathEntry[0], null); | |
createOutputFolder(binFolder); | |
addSystemLibraries(); | |
} | |
public TestProject(final IProject project) throws CoreException | |
{ | |
if (project == null) | |
{ | |
throw new NullPointerException("project should not be null"); | |
} | |
this.project = project; | |
this.javaProject = JavaCore.create(project); | |
this.sourceFolder = findSourceFolder(); | |
} | |
private IPackageFragmentRoot findSourceFolder() throws JavaModelException | |
{ | |
for (IPackageFragmentRoot pfr : javaProject.getAllPackageFragmentRoots()) | |
{ | |
if (pfr.getKind() == IPackageFragmentRoot.K_SOURCE) | |
{ | |
return pfr; | |
} | |
} | |
return null; | |
} | |
public IProject getProject() | |
{ | |
return project; | |
} | |
public IJavaProject getJavaProject() | |
{ | |
return javaProject; | |
} | |
public void addJar(String plugin, String jar) throws MalformedURLException, IOException, JavaModelException | |
{ | |
Path result = findFileInPlugin(plugin, jar); | |
IClasspathEntry[] oldEntries = javaProject.getRawClasspath(); | |
IClasspathEntry[] newEntries = new IClasspathEntry[oldEntries.length + 1]; | |
System.arraycopy(oldEntries, 0, newEntries, 0, oldEntries.length); | |
newEntries[oldEntries.length] = JavaCore.newLibraryEntry(result, null, null); | |
javaProject.setRawClasspath(newEntries, null); | |
String log = "\n"+javaProject.getProject().getName()+"\n"+String.valueOf(javaProject.getRawClasspath().length)+"\n"; | |
for(int ii=0; ii < javaProject.getRawClasspath().length; ii++) | |
{ | |
log = log + javaProject.getRawClasspath()[ii].getPath().toString()+"\n"; | |
} | |
if(javaProject.getRawClasspath().length==0) | |
{ | |
log = log + "Classpath not initialized !\n"; | |
} | |
ResourcesPlugin.getPlugin().getLog().log(new Status(0,"testOutput",log)); | |
} | |
public IPackageFragment createPackage(String name) throws CoreException | |
{ | |
if (sourceFolder == null) | |
sourceFolder = createSourceFolder("src"); | |
return sourceFolder.createPackageFragment(name, false, null); | |
} | |
public IType createType(IPackageFragment pack, String cuName, String source) throws JavaModelException | |
{ | |
StringBuffer buf = new StringBuffer(); | |
buf.append("package " + pack.getElementName() + ";\n"); | |
buf.append("\n"); | |
buf.append(source); | |
ICompilationUnit cu = pack.createCompilationUnit(cuName, buf.toString(), false, null); | |
return cu.getTypes()[0]; | |
} | |
/** | |
* Creates multiple classes in project. The content of <code>source</code> should be in form - | |
* '#' char (separator for classes) followed by Class name, new line and after that class source without package declaration.<br> | |
* Example: | |
* | |
* <pre> | |
* #ImplementsRemote | |
* public class ImplementsRemote implements java.rmi.Remote | |
* { | |
* } | |
* | |
* #NoDefaultConstructor | |
* public class NoDefaultConstructor implements java.io.Serializable | |
* { | |
* public NoDefaultConstructor(String param) { | |
* } | |
* } | |
* </pre> | |
* | |
* This method is useful if lots of small classes should be created from a source file. | |
* | |
* @param sourcesFilePath | |
* @return map of className->IType. that have been created | |
* @throws Exception | |
*/ | |
public Map<String, IType> createTypes(IPackageFragment pack, String source) throws Exception | |
{ | |
Map<String, IType> types = new HashMap<String, IType>(); | |
int startPos = 0; | |
while ((startPos = source.indexOf(CLASS_SEPARATOR)) > -1) | |
{ | |
int endPos = source.indexOf(CLASS_SEPARATOR, startPos + 1); | |
if (endPos == -1) { | |
endPos = source.length(); | |
} | |
String src = source.substring(startPos + 1, endPos); | |
source = source.substring(endPos); | |
String className = src.substring(0, src.indexOf('\n')).replaceAll("\r", "").trim(); | |
src = src.substring(src.indexOf('\n') + 1); | |
types.put(className, createType(pack, className + ".java", src)); | |
} | |
return types; | |
} | |
public void dispose() throws CoreException | |
{ | |
JobUtils.waitForJobs(); | |
try { | |
project.refreshLocal(IResource.DEPTH_INFINITE, null); | |
project.delete(true, true, null); | |
} catch (ResourceException re) { | |
/* | |
* silently swallow the resource exception. For some reason this exception gets thrown | |
* from time to time and reports the test failing. The project deletion itself happens | |
* after the test has completed and a failure will not report a problem in the test. | |
* Only ResourceException is caught in order not to hide unexpected errors. | |
*/ | |
return; | |
} | |
} | |
public void close() throws CoreException | |
{ | |
JobUtils.waitForJobs(); | |
project.close(new NullProgressMonitor()); | |
} | |
private IFolder createBinFolder() throws CoreException | |
{ | |
IFolder binFolder = project.getFolder("bin"); | |
binFolder.create(false, true, null); | |
return binFolder; | |
} | |
private void setJavaNature() throws CoreException | |
{ | |
IProjectDescription description = project.getDescription(); | |
description.setNatureIds(new String[] { JavaCore.NATURE_ID }); | |
project.setDescription(description, null); | |
} | |
private void createOutputFolder(IFolder binFolder) throws JavaModelException | |
{ | |
IPath outputLocation = binFolder.getFullPath(); | |
javaProject.setOutputLocation(outputLocation, null); | |
} | |
public IPackageFragmentRoot createSourceFolder(String name) throws CoreException | |
{ | |
IFolder folder = project.getFolder(name); | |
folder.create(false, true, null); | |
IPackageFragmentRoot root = javaProject.getPackageFragmentRoot(folder); | |
IClasspathEntry[] oldEntries = javaProject.getRawClasspath(); | |
IClasspathEntry[] newEntries = new IClasspathEntry[oldEntries.length + 1]; | |
System.arraycopy(oldEntries, 0, newEntries, 0, oldEntries.length); | |
newEntries[oldEntries.length] = JavaCore.newSourceEntry(root.getPath()); | |
javaProject.setRawClasspath(newEntries, null); | |
this.sourceFolder = root; | |
String log = "\n"+javaProject.getProject().getName()+"\n"+String.valueOf(javaProject.getRawClasspath().length)+"\n"; | |
for(int ii=0; ii < javaProject.getRawClasspath().length; ii++) | |
{ | |
log = log + javaProject.getRawClasspath()[ii].getPath().toString()+"\n"; | |
} | |
if(javaProject.getRawClasspath().length==0) | |
{ | |
log = log + "Classpath not initialized !\n"; | |
} | |
ResourcesPlugin.getPlugin().getLog().log(new Status(0,"testOutput",log)); | |
return root; | |
} | |
private void addSystemLibraries() throws JavaModelException | |
{ | |
IClasspathEntry[] oldEntries = javaProject.getRawClasspath(); | |
IClasspathEntry[] newEntries = new IClasspathEntry[oldEntries.length + 1]; | |
System.arraycopy(oldEntries, 0, newEntries, 0, oldEntries.length); | |
newEntries[oldEntries.length] = JavaRuntime.getDefaultJREContainerEntry(); | |
javaProject.setRawClasspath(newEntries, null); | |
String log = "\n"+javaProject.getProject().getName()+"\n"+String.valueOf(javaProject.getRawClasspath().length)+"\n"; | |
for(int ii=0; ii < javaProject.getRawClasspath().length; ii++) | |
{ | |
log = log + javaProject.getRawClasspath()[ii].getPath().toString()+"\n"; | |
} | |
if(javaProject.getRawClasspath().length==0) | |
{ | |
log = log + "Classpath not initialized !\n"; | |
} | |
ResourcesPlugin.getPlugin().getLog().log(new Status(0,"testOutput",log)); | |
} | |
private Path findFileInPlugin(String plugin, String file) throws MalformedURLException, IOException | |
{ | |
Bundle pluginBundle = Platform.getBundle(plugin); | |
URL jarURL = new URL(pluginBundle.getEntry("/"), file); | |
URL localJarURL = FileLocator.toFileURL(jarURL); | |
return new Path(localJarURL.getPath()); | |
} | |
public IPackageFragmentRoot getSourceFolder() | |
{ | |
return sourceFolder; | |
} | |
/** | |
* | |
* @return the container corresponding to the package fragment root, i.e. the source folder.<br> | |
* If this project is a jar/zip (if this is possible at all), the method will return null. | |
*/ | |
public IContainer getSourceFolderContainer() | |
{ | |
try{ | |
IResource res = getSourceFolder().getCorrespondingResource(); | |
if(res==null) { | |
return null; | |
}else { | |
IContainer retVal = (IContainer) res; | |
return retVal; | |
} | |
}catch(JavaModelException ex) { | |
return null; | |
}catch(ClassCastException ex) { | |
return null; | |
} | |
} | |
public IFolder createFolder(final String folderName) throws CoreException | |
{ | |
ContractChecker.nullCheckParam(folderName, "folderName"); | |
final IFolder folder = this.project.getFolder(folderName); | |
folder.create(false, true, null); | |
return folder; | |
} | |
/** | |
* Set the project root as source folder | |
* @throws JavaModelException | |
*/ | |
public void assignProjectRootAsSourceFolder() throws JavaModelException | |
{ | |
IClasspathEntry defaultSrcFolderEntry = JavaCore.newSourceEntry(project.getFullPath()); | |
IClasspathEntry[] oldCp = javaProject.getRawClasspath(); | |
IClasspathEntry[] newCp = new IClasspathEntry[oldCp.length + 1]; | |
System.arraycopy(oldCp, 0, newCp, 0, oldCp.length); | |
newCp[newCp.length - 1] = defaultSrcFolderEntry; | |
javaProject.setRawClasspath(newCp, null); | |
this.sourceFolder = TestProjectsUtils.getSourceFolder(project, ""); | |
String log = "\n"+javaProject.getProject().getName()+"\n"+String.valueOf(javaProject.getRawClasspath().length)+"\n"; | |
for(int ii=0; ii < javaProject.getRawClasspath().length; ii++) | |
{ | |
log = log + javaProject.getRawClasspath()[ii].getPath().toString()+"\n"; | |
} | |
if(javaProject.getRawClasspath().length==0) | |
{ | |
log = log + "Classpath not initialized !\n"; | |
} | |
ResourcesPlugin.getPlugin().getLog().log(new Status(0,"testOutput",log)); | |
} | |
} |