org.symbian.tools.wrttools/src/org/symbian/tools/wrttools/util/ProjectUtils.java
author Eugene Ostroukhov <eugeneo@symbian.org>
Wed, 20 Jan 2010 18:00:15 -0800
changeset 38 954dbf7baac6
parent 30 50ffca984095
child 45 aa2fb3fcc303
permissions -rw-r--r--
Merged with the most current version

/**
 * Copyright (c) 2009 Symbian Foundation and/or its subsidiary(-ies).
 * All rights reserved.
 * This component and the accompanying materials are made available
 * under the terms of the License "Eclipse Public License v1.0"
 * which accompanies this distribution, and is available
 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
 *
 * Initial Contributors:
 * Symbian Foundation - initial contribution.
 * Contributors:
 * Description:
 * Overview:
 * Details:
 * Platforms/Drives/Compatibility:
 * Assumptions/Requirement/Pre-requisites:
 * Failures and causes:
 */
package org.symbian.tools.wrttools.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import javax.swing.filechooser.FileSystemView;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
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.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.wst.jsdt.internal.ui.wizards.buildpaths.BuildPathsBlock;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
import org.eclipse.wst.validation.ValidationFramework;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.symbian.tools.wrttools.Activator;
import org.symbian.tools.wrttools.dialogs.AptanaProjectSelectionDialog;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class ProjectUtils {
	private static final String DEFAULT_APTANA_WORKSPACE = "Aptana Studio Workspace";
	private static final String WRT_PREVIEW_MAIN_HTML = "wrt_preview_main.html";
	public static final String PREVIEW_FOLDER = "preview";
	public static final String PREVIEW_FRAME_FILE = "wrt_preview_frame.html";

	@SuppressWarnings("restriction")
	public static IProject createWrtProject(String name, URI uri,
			IProgressMonitor monitor) throws CoreException {
		monitor.beginTask("Create project resources", 20);
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		IProject project = workspace.getRoot().getProject(name);
		ValidationFramework.getDefault().addValidationBuilder(project);
		BuildPathsBlock.createProject(project, uri, new SubProgressMonitor(
				monitor, 10));

		BuildPathsBlock.addJavaNature(project, new SubProgressMonitor(monitor,
				10));

		// TODO: Build path, super type, etc.
		// BuildPathsBlock.flush(classPathEntries, javaScriptProject, superType,
		// monitor)


		monitor.done();
		return project;
	}

	public static void addPreviewer(IProject project, IPath mainHtml) {
		URI archive = getPreviewerArchive();
		try {
			if (archive != null) {
				ZipInputStream stream = new ZipInputStream(archive.toURL().openStream());
				ZipEntry entry;
				while ((entry = stream.getNextEntry()) != null) {
					if (!entry.isDirectory()) {
						copyFile(project, entry.getName(), stream, entry.getSize(), new NullProgressMonitor());
					} else {
						IFolder folder = project.getFolder(entry.getName());
						if (!folder.exists()) {
							folder.create(false, true, new NullProgressMonitor());
						}
					}
					stream.closeEntry();
				}
			}
			createPreviewerHomePage(project, mainHtml);
		} catch (IOException e) {
			StatusManager.getManager().handle(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Unable to add previewer to project"));
		} catch (CoreException e) {
			StatusManager.getManager().handle(e, Activator.PLUGIN_ID);
		}
	}

	@SuppressWarnings("restriction")
	private static void createPreviewerHomePage(IProject project, IPath mainHtml)
			throws CoreException, IOException {
		IFile file = project.getFile(mainHtml + ".html");
		if (file.exists()) {
			IFile newFile = project.getFile(WRT_PREVIEW_MAIN_HTML);
			file.copy(newFile.getFullPath(), false, new NullProgressMonitor());
			IModelManager modelManager = StructuredModelManager
					.getModelManager();
			IDOMModel model = (IDOMModel) modelManager
					.getModelForEdit(newFile);
			if (model != null) {
				try {
					addJS(model);
				} finally {
					model.releaseFromEdit();
				}
			}
		}
	}

	@SuppressWarnings("restriction")
	private static void addJS(IDOMModel model) throws IOException, CoreException {
		IDOMDocument document = model.getDocument();
		Element documentElement = document.getDocumentElement();
		if (documentElement != null) {
			NodeList elementsByTagName = documentElement.getElementsByTagName("head");
			if (elementsByTagName.getLength() == 1) { // We do not want to handle malformed HTMLs
				Element head = (Element) elementsByTagName.item(0);
				Element script = document.createElement("script");
				script.setAttribute("language", "JavaScript");
				script.setAttribute("type", "text/javascript");
				script.setAttribute("src", "preview/script/lib/loader.js");
				head.insertBefore(script, head.getFirstChild());
				model.save();
			}
		}
	}

	private static URI getPreviewerArchive() {
		File file = getPreviewerZip();
		if (file.isFile()) {
			return file.toURI();
		}
		Display display = Display.getDefault();
		display.syncExec(new Runnable() {
			@Override
			public void run() {
				importPreviewer();
			}
		});
		if (file.isFile()) {
			return file.toURI();
		}
		return null;
	}

	private static File getPreviewerZip() {
		return Activator.getDefault().getStateLocation()
				.append("previewer.zip").toFile();
	}

	private static void importPreviewer() {
		AptanaProjectSelectionDialog dialog = new AptanaProjectSelectionDialog(
				PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
		int open = dialog.open();
		if (open == Window.OK) {
			File project = dialog.getProject();
			try {
				zipPreviewer(project);
			} catch (IOException e) {
				StatusManager
						.getManager()
						.handle(
								new Status(
										IStatus.ERROR,
										Activator.PLUGIN_ID,
										"Failed to create Web Runtime previewer archive.",
										e), StatusManager.SHOW);
			}
		}
	}

	private static void zipPreviewer(File project) throws IOException {
		ZipOutputStream stream = new ZipOutputStream(new FileOutputStream(
				getPreviewerZip()));
		try {
			zip(new File(project, PREVIEW_FOLDER), stream, PREVIEW_FOLDER + "/");
			zipFile(new File(project, PREVIEW_FRAME_FILE),
					PREVIEW_FRAME_FILE, stream);
		} finally {
			stream.close();
		}
	}

	private static void zip(File folder, ZipOutputStream stream, String path)
			throws IOException {
		ZipEntry entry = new ZipEntry(path);
		stream.putNextEntry(entry);
		stream.closeEntry();
		File[] files = folder.listFiles();
		for (File file : files) {
			if (file.isFile()) {
				zipFile(file, path + file.getName(), stream);
			} else {
				zip(file, stream, path + file.getName() + "/");
			}
		}
	}

	private static void zipFile(File file, String zipEntry,
			ZipOutputStream stream) throws IOException, FileNotFoundException {
		ZipEntry entry = new ZipEntry(zipEntry);
		stream.putNextEntry(entry);
		BufferedInputStream inputStream = new BufferedInputStream(
				new FileInputStream(file));
		try {
			copy(inputStream, stream);
		} finally {
			inputStream.close();
		}
		stream.closeEntry();
	}

	private static void copy(InputStream in, OutputStream out)
			throws IOException {
		byte[] buffer = new byte[131072]; // 128k - should be enough for most
		// JS/CSS files
		int count;
		while ((count = in.read(buffer)) > 0) {
			out.write(buffer, 0, count);
		}
	}

	public static String getDefaultAptanaLocation() {
		File myDocuments = FileSystemView.getFileSystemView()
				.getDefaultDirectory();
		File file = new File(myDocuments, DEFAULT_APTANA_WORKSPACE); // Windows
		if (file.exists()) {
			return file.getAbsolutePath();
		}
		file = new File(myDocuments, "Documents" + File.separator + DEFAULT_APTANA_WORKSPACE); // Mac OS X
		if (file.exists()) {
			return file.getAbsolutePath();
		}
		return "";
	}

	public static boolean isAptanaProject(File f) {
		return new File(f, PREVIEW_FOLDER).isDirectory()
				&& new File(f, PREVIEW_FRAME_FILE).isFile();
	}

	public static void copyFile(IProject project, String name, ZipInputStream stream,
			long size, IProgressMonitor monitor) throws CoreException,
			IOException {
		IFile file = project.getFile(name);
		file.create(new NonClosingStream(stream), true,
				new SubProgressMonitor(monitor, 1));
	}

	public static void importPreviewer(URI locationURI) {
		if (!getPreviewerZip().exists()) {
			File file = new File(locationURI);
			try {
				zipPreviewer(file);
			} catch (IOException e) {
				Activator.log(e);
			}
		}
	}

	public static boolean isAptanaProject(URI locationURI) {
		return isAptanaProject(new File(locationURI));
	}
}