/********************************************************************** * Copyright (c) 2005-2009 ant4eclipse project team. * * 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: * Nils Hartmann, Daniel Kasmeroglu, Gerd Wuetherich **********************************************************************/ package org.ant4eclipse.testframework; import org.ant4eclipse.lib.core.ClassName; import org.ant4eclipse.lib.core.util.Utilities; import org.ant4eclipse.lib.jdt.model.project.JavaProjectRole; import org.junit.Assert; import java.io.File; import java.util.Hashtable; import java.util.LinkedList; import java.util.List; import java.util.Map; /** * Adds JDT-specific features to {@link EclipseProjectBuilder} * * @author Nils Hartmann (nils@nilshartmann.net) */ public class JdtProjectBuilder extends EclipseProjectBuilder { private List<String> _classpathEntries; /** * Holds all SourceClasses (grouped by their source folders) that should be added to this project. * * <ul> * <li>Key: the source folder * <li>Value: {@link SourceClasses} the SourceClasses in the source folder * </ul> */ private Map<String, List<SourceClass>> _sourceClasses; /** * Returns a "pre-configured" {@link JdtProjectBuilder}, that already has set: * <ul> * <li>a java builder</li> * <li>the java nature * <li> * <li>the JRE container classpath entry</li> * <li>a source folder (<tt>src</tt>)</li> * <li>a default output folder (<tt>bin</tt>)</li> * </ul> * * The builder returned can be used to further customize the project * * @param projectName * The name of the project * @return the pre-configured JdtEclipseProjectBuilder */ public static JdtProjectBuilder getPreConfiguredJdtBuilder(String projectName) { JdtProjectBuilder result = new JdtProjectBuilder(projectName); result.withJreContainerClasspathEntry(); result.withSrcClasspathEntry("src", false); result.withOutputClasspathEntry("bin"); return result; } /** * Constructs a new JdtEclipseProjectBuilder instance with the project name. * * <p> * The constructor adds a {@link #withJavaBuilder() javaBuilder} and a {@link #withJavaNature() javaNature} to the * project * * @param projectName */ public JdtProjectBuilder(String projectName) { super(projectName); this._sourceClasses = new Hashtable<String, List<SourceClass>>(); this._classpathEntries = new LinkedList<String>(); // All JDT-Projects have a java builder and a java nature withJavaNature(); withJavaBuilder(); } /** * Adds a {@link SourceClass} to this project * * @param sourceFolder * the sourcefolder for this class * @param className * The full qualified classname for this class * @return the {@link SourceClass} instance */ public SourceClass withSourceClass(String sourceFolder, String className) { SourceClass sourceClass = new SourceClass(this, className); List<SourceClass> sourceClasses = this._sourceClasses.get(sourceFolder); if (sourceClasses == null) { sourceClasses = new LinkedList<SourceClass>(); this._sourceClasses.put(sourceFolder, sourceClasses); } sourceClasses.add(sourceClass); return sourceClass; } protected JdtProjectBuilder withJavaBuilder() { return (JdtProjectBuilder) withBuilder("org.eclipse.jdt.core.javabuilder"); } /** * Adds <tt>entry</tt> to the list of classpath entries for this project. * * <p> * the classpath entry must be a well formatted line of xml, that is valid in a <tt>.classpath</tt> file. * * @param entry * The xml-entry * @return this */ public JdtProjectBuilder withClasspathEntry(String entry) { Assert.assertNotNull(entry); this._classpathEntries.add(entry); return this; } protected JdtProjectBuilder withJavaNature() { return (JdtProjectBuilder) withNature(JavaProjectRole.JAVA_NATURE); } public JdtProjectBuilder withSrcClasspathEntry(String path, boolean exported) { String line = String .format("<classpathentry kind='src' path='%s' exported='%s'/>", path, Boolean.valueOf(exported)); return withClasspathEntry(line); } public JdtProjectBuilder withSrcClasspathEntry(String path, String output, boolean exported) { String line = String.format("<classpathentry kind='src' path='%s' output='%s' exported='%s'/>", path, output, Boolean.valueOf(exported)); return withClasspathEntry(line); } public JdtProjectBuilder withContainerClasspathEntry(String path) { String line = String.format("<classpathentry kind='con' path='%s'/>", path); return withClasspathEntry(line); } public JdtProjectBuilder withVarClasspathEntry(String path) { String line = String.format("<classpathentry kind='var' path='%s'/>", path); return withClasspathEntry(line); } public JdtProjectBuilder withOutputClasspathEntry(String path) { String line = String.format(" <classpathentry kind='output' path='%s'/>", path); return withClasspathEntry(line); } /** * Adds a JRE_CONTAINER to the classpath * * @return */ public JdtProjectBuilder withJreContainerClasspathEntry() { return withClasspathEntry("<classpathentry kind='con' path='org.eclipse.jdt.launching.JRE_CONTAINER'/>"); } /** * Adds a JRE_CONTAINER with the given containerName to the classpath * * @return */ public JdtProjectBuilder withJreContainerClasspathEntry(String containerName) { return withClasspathEntry(String.format( "<classpathentry kind='con' path='org.eclipse.jdt.launching.JRE_CONTAINER/%s'/>", containerName)); } /** * {@inheritDoc} */ @Override protected void createArtefacts(File projectDir) { super.createArtefacts(projectDir); createClasspathFile(projectDir); for (Map.Entry<String, List<SourceClass>> entry : this._sourceClasses.entrySet()) { String sourceFolder = entry.getKey(); List<SourceClass> sourceClasses = entry.getValue(); for (SourceClass sourceClass : sourceClasses) { createSourceClass(projectDir, sourceFolder, sourceClass); } } } protected void createSourceClass(File projectDir, String sourceFolder, SourceClass sourceClass) { File sourceDir = new File(projectDir, sourceFolder); if (!sourceDir.exists()) { sourceDir.mkdirs(); } Assert.assertTrue(sourceDir.isDirectory()); ClassName className = ClassName.fromQualifiedClassName(sourceClass.getClassName()); File packageDir = new File(sourceDir, className.getPackageAsDirectoryName()); if (!packageDir.exists()) { packageDir.mkdirs(); } Assert.assertTrue(packageDir.isDirectory()); File sourcefile = new File(sourceDir, className.asSourceFileName()); StringTemplate classTemplate = new StringTemplate(); classTemplate.append("package ${packageName};").nl(); classTemplate.append("public class ${className} {").nl(); classTemplate.append(sourceClass.generateUsageCode()).nl(); classTemplate.append("} // end of class").nl(); classTemplate.replace("packageName", className.getPackageName()); classTemplate.replace("className", className.getClassName()); Utilities.writeFile(sourcefile, classTemplate.toString(), Utilities.ENCODING); } protected void createClasspathFile(File projectDir) { StringBuilder dotClasspath = new StringBuilder(); dotClasspath.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>").append(Utilities.NL).append("<classpath>") .append(Utilities.NL); for (String entry : this._classpathEntries) { dotClasspath.append(entry).append(Utilities.NL); } dotClasspath.append("</classpath>").append(Utilities.NL); File dotClasspathFile = new File(projectDir, ".classpath"); Utilities.writeFile(dotClasspathFile, dotClasspath.toString(), "UTF-8"); } }