package thahn.java.agui.ide.eclipse.wizard; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.util.Arrays; import java.util.HashSet; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileInfo; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.filesystem.IFileSystem; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; 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.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; 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.IStatus; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.launching.JavaRuntime; import thahn.java.agui.ide.eclipse.preferences.AguiPreferenceConstants; import thahn.java.agui.ide.eclipse.preferences.AguiPrefs; import thahn.java.agui.ide.eclipse.project.AguiConstants; import thahn.java.agui.ide.eclipse.project.AguiNature; import thahn.java.agui.ide.eclipse.wizard.template.ResourceIndicator; public class AguiProjectMaker { public static final String START_SEPARATOR = "${"; public static final String END_SEPARATOR = "}"; public static final int MF_PACKAGE_NAME_HASH = "${package}".hashCode(); public static final int MF_MAIN_ACTIVITY_NAME_HASH = "${mainActivityName}".hashCode(); public static final int STRING_APP_NAME_HASH = "${app_name}".hashCode(); public static final String MF_PACKAGE_NAME = "\\$\\{package\\}"; public static final String MF_MAIN_ACTIVITY_NAME = "\\$\\{mainActivityName\\}"; public static final String STRING_APP_NAME = "\\$\\{app_name\\}"; private String mApplicationName; private String mPackageName; private String mActivityName; public AguiProjectMaker(String mApplicationName, String mPackageName, String mActivityName) { this.mApplicationName = mApplicationName; this.mPackageName = mPackageName; this.mActivityName = mActivityName; } /** * This creates the project in the workspace. * * @param description * @param projectHandle * @param monitor * @throws CoreException * @throws OperationCanceledException */ void createProject(IProject proj, IProgressMonitor monitor) throws CoreException, OperationCanceledException { try { IWorkspace workspace = ResourcesPlugin.getWorkspace(); IProjectDescription description = workspace.newProjectDescription(proj.getName()); // monitor.beginTask("", 2000); proj.create(description, new SubProgressMonitor(monitor, 10)); if (monitor.isCanceled()) { throw new OperationCanceledException(); } proj.open(IResource.BACKGROUND_REFRESH, monitor); description.setLocationURI(proj.getLocationURI()); AguiNature.addNatureToProjectDescription(proj, JavaCore.NATURE_ID, monitor); AguiNature.addNatureToProjectDescription(proj, AguiNature.NATURE_ID, monitor); AguiNature.configureBuilder(proj); // IJavaProject javaProject = JavaCore.create(proj); // ref agui lib String sdkLibLocation = AguiPrefs.getInstance().getSdkJarLocation(); IClasspathEntry aguiLib = JavaCore.newLibraryEntry(new Path(sdkLibLocation), null, null); // ref java lib HashSet<IClasspathEntry> entries = new HashSet<IClasspathEntry>(); entries.addAll(Arrays.asList(javaProject.getRawClasspath())); entries.add(JavaRuntime.getDefaultJREContainerEntry()); entries.add(aguiLib); javaProject.setRawClasspath(entries.toArray(new IClasspathEntry[entries.size()]), monitor); // monitor.worked(1000); // createAguiProject(javaProject, monitor); // monitor.worked(1000); // populate("src", container, proj); setupSourceFolders(javaProject, new String[]{"src", "gen"}, monitor); // } catch (Exception ioe) { ioe.printStackTrace(); IStatus status = new Status(IStatus.ERROR, "NewFileWizard", IStatus.OK, ioe.getLocalizedMessage(), null); throw new CoreException(status); } finally { monitor.done(); } } private void createAguiProject(IJavaProject javaProject, IProgressMonitor monitor) throws CoreException, IOException { IProject proj = javaProject.getProject(); IContainer container = (IContainer) proj; // createFolder(container, "src", monitor); createSrcPakcage(proj, "src/", mPackageName, mActivityName, monitor); createFolder(container, "gen", monitor); createSrcPakcage(proj, "gen/", mPackageName, mActivityName, monitor); javaProject.setOutputLocation(createFolder(container, "bin", monitor).getFullPath(), monitor); // createFolder(container, "res", monitor); createFolder(container, "res/drawable", monitor); createFolder(container, "res/drawable-hdpi", monitor); createFolder(container, "res/layout", monitor); createFolder(container, "res/values", monitor); // BufferedInputStream activityBis = new BufferedInputStream(copyTemplate("ActivityTemplate.txt")); addFileToProject(container, new Path("/src/"+mPackageName.replace(".", "/")+"/"+mActivityName+".java"), activityBis, monitor); activityBis.close(); // BufferedInputStream manifestBis = new BufferedInputStream(copyTemplate("AguiManifestTemplate.xml"));//copyManifest(mPackageName, mActivityName)); addFileToProject(container, new Path("AguiManifest.xml"), manifestBis, monitor); manifestBis.close(); // BufferedInputStream icBis = new BufferedInputStream(AguiPlugin.getBundleAbsolutePath("icons/ic_launcher.png").openStream()); addFileToProject(container, new Path("res/drawable-hdpi/ic_launcher.png"), icBis, monitor); icBis.close(); // BufferedInputStream stringBis = new BufferedInputStream(copyTemplate("stringsTemplate.xml"));//copyValues(mApplicationName, mPackageName, mActivityName)); addFileToProject(container, new Path("res/values/string.xml"), stringBis, monitor); stringBis.close(); // BufferedInputStream layoutBis = new BufferedInputStream(copyTemplate("mainTemplate.xml"));//copyFile("mainTemplate.xml")); addFileToProject(container, new Path("res/layout/main.xml"), layoutBis, monitor); layoutBis.close(); // BufferedInputStream buildConfigBis = new BufferedInputStream(copyTemplate("BuildConfigTemplate.txt"));//copyFile("mainTemplate.xml")); addFileToProject(container, new Path("gen/"+mPackageName.replace(".", "/")+"/"+AguiConstants.BUILD_CONFIG_JAVA), buildConfigBis, monitor); buildConfigBis.close(); // // proj.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null); } private IFolder createFolder(IContainer container, String folderName, IProgressMonitor monitor) throws CoreException { IFolder srcFolder = container.getFolder(new Path(folderName)); srcFolder.create(true, true, monitor); return srcFolder; } private void createSrcPakcage(IProject proj, String prefix, String packageName, String activityName, IProgressMonitor monitor) throws CoreException { IFolder pkgFolder = proj.getFolder(prefix); if (packageName.contains(".")) { String[] components = packageName.replace(".", "/").split("/"); for (String component : components) { pkgFolder = pkgFolder.getFolder(component); if (!pkgFolder.exists()) { pkgFolder.create(true /* force */, true /* local */, new SubProgressMonitor(monitor, 10)); } } } else { pkgFolder = pkgFolder.getFolder(packageName); if (!pkgFolder.exists()) { pkgFolder.create(true /* force */, true /* local */, new SubProgressMonitor(monitor, 10)); } } } /** * Adds a new file to the project. * * @param container * @param path * @param contentStream * @param monitor * @throws CoreException */ public void addFileToProject(IContainer container, Path path, InputStream contentStream, IProgressMonitor monitor) throws CoreException { final IFile file = container.getFile(path); if (file.exists()) { file.setContents(contentStream, true, true, monitor); } else { file.create(contentStream, true, monitor); } } public InputStream copyTemplate(String template) throws CoreException { return copyTemplate(ResourceIndicator.class.getResourceAsStream(template)); } private InputStream copyTemplate(InputStream input) throws CoreException { StringBuilder sb = new StringBuilder(); try { /* We want to be truly OS-agnostic */ String line; final String newline = System.getProperty("line.separator"); BufferedReader reader = new BufferedReader(new InputStreamReader(input)); try { while ((line = reader.readLine()) != null) { if (line.contains(START_SEPARATOR)) { int start = line.indexOf(START_SEPARATOR); int end = line.indexOf(END_SEPARATOR)+1; int which = line.substring(start, end).hashCode(); if (which == MF_PACKAGE_NAME_HASH) { line = line.replaceAll(AguiProjectMaker.MF_PACKAGE_NAME, mPackageName); } else if(which == MF_MAIN_ACTIVITY_NAME_HASH) { line = line.replaceAll(AguiProjectMaker.MF_MAIN_ACTIVITY_NAME, mActivityName); } else if(which == STRING_APP_NAME_HASH) { line = line.replaceAll(AguiProjectMaker.STRING_APP_NAME, mApplicationName); } } sb.append(line); sb.append(newline); } } finally { reader.close(); } } catch (IOException ioe) { IStatus status = new Status(IStatus.ERROR, "NewFileWizard", IStatus.OK, ioe.getLocalizedMessage(), null); throw new CoreException(status); } return new ByteArrayInputStream(sb.toString().getBytes()); } /** * Adds the given folder to the project's class path. * * @param javaProject The Java Project to update. * @param sourceFolders Template Parameters. * @param monitor An existing monitor. * @throws JavaModelException if the classpath could not be set. */ private void setupSourceFolders(IJavaProject javaProject, String[] sourceFolders, IProgressMonitor monitor) throws JavaModelException { IProject project = javaProject.getProject(); // get the list of entries. IClasspathEntry[] entries = javaProject.getRawClasspath(); // remove the project as a source folder (This is the default) entries = removeSourceClasspath(entries, project); // add the source folders. for (String sourceFolder : sourceFolders) { IFolder srcFolder = project.getFolder(sourceFolder); // remove it first in case. entries = removeSourceClasspath(entries, srcFolder); entries = ProjectHelper.addEntryToClasspath(entries, JavaCore.newSourceEntry(srcFolder.getFullPath())); } javaProject.setRawClasspath(entries, new SubProgressMonitor(monitor, 10)); } /** * Removes the corresponding source folder from the class path entries if * found. * * @param entries The class path entries to read. A copy will be returned. * @param folder The parent source folder to remove. * @return A new class path entries array. */ private IClasspathEntry[] removeSourceClasspath(IClasspathEntry[] entries, IContainer folder) { if (folder == null) { return entries; } IClasspathEntry source = JavaCore.newSourceEntry(folder.getFullPath()); int n = entries.length; for (int i = n - 1; i >= 0; i--) { if (entries[i].equals(source)) { IClasspathEntry[] newEntries = new IClasspathEntry[n - 1]; if (i > 0) System.arraycopy(entries, 0, newEntries, 0, i); if (i < n - 1) System.arraycopy(entries, i + 1, newEntries, i, n - i - 1); n--; entries = newEntries; } } return entries; } public void populate(String source, IContainer container, IProject project) { // Copy IFileSystem fileSystem = EFS.getLocalFileSystem(); // File source = (File) new File(); IFileStore sourceDir = new ReadWriteFileStore( fileSystem.getStore(container.getFolder(new Path(source)).getLocationURI()//source.toURI() )); IFileStore destDir = new ReadWriteFileStore( fileSystem.getStore(getAbsolutePath(project))); try { sourceDir.copy(destDir, EFS.OVERWRITE, null); } catch (CoreException e) { // AdtPlugin.log(e, null); } } /** * Returns an absolute path to the given resource * * @param resource the resource to look up a path for * @return an absolute file system path to the resource */ public static IPath getAbsolutePath(IResource resource) { IPath location = resource.getRawLocation(); if (location != null) { return location.makeAbsolute(); } else { IWorkspace workspace = ResourcesPlugin.getWorkspace(); IWorkspaceRoot root = workspace.getRoot(); IPath workspacePath = root.getLocation(); return workspacePath.append(resource.getFullPath()); } } /** * In a sample we never duplicate source files as read-only. * This creates a store that read files attributes and doesn't set the r-o flag. */ private static class ReadWriteFileStore extends FileStoreAdapter { public ReadWriteFileStore(IFileStore store) { super(store); } // Override when reading attributes @Override public IFileInfo fetchInfo(int options, IProgressMonitor monitor) throws CoreException { IFileInfo info = super.fetchInfo(options, monitor); info.setAttribute(EFS.ATTRIBUTE_READ_ONLY, false); return info; } // Override when writing attributes @Override public void putInfo(IFileInfo info, int options, IProgressMonitor storeMonitor) throws CoreException { info.setAttribute(EFS.ATTRIBUTE_READ_ONLY, false); super.putInfo(info, options, storeMonitor); } @Deprecated @Override public IFileStore getChild(IPath path) { IFileStore child = super.getChild(path); if (!(child instanceof ReadWriteFileStore)) { child = new ReadWriteFileStore(child); } return child; } @Override public IFileStore getChild(String name) { return new ReadWriteFileStore(super.getChild(name)); } } }