/******************************************************************************* * Copyright (c) 2012 Arapiki Solutions Inc. * 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: * "Peter Smith <psmith@arapiki.com>" - initial API and * implementation and/or initial documentation *******************************************************************************/ package com.buildml.eclipse.wizards; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; 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.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.wizard.Wizard; import org.eclipse.ui.INewWizard; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWizard; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.IDE; import com.buildml.eclipse.utils.AlertDialog; import com.buildml.eclipse.utils.EclipsePartUtils; import com.buildml.model.BuildStoreFactory; import com.buildml.model.BuildStoreVersionException; import com.buildml.model.IBuildStore; import com.buildml.model.IFileMgr; import com.buildml.model.IPackageRootMgr; import com.buildml.scanner.FatalBuildScannerError; import com.buildml.utils.errors.ErrorCode; /** * This class provides Eclipse wizard functionality for creating a new empty BuildML * file. */ public class NewBmlFile extends Wizard implements INewWizard { /*=====================================================================================* * FIELDS/TYPES *=====================================================================================*/ /** * The one-and-only UI wizard page that'll request the user to enter the new file name, * and the file's parent container. */ private NewBmlFilePage page; /** * The resource that was selected in the Eclipse UI, when the "new" operation was * invoked. If valid, this is used as the parent project/folder for the new file. */ private ISelection selection; /*=====================================================================================* * CONSTRUCTORS *=====================================================================================*/ /** * Create a new NewBmlFile wizard, which is invoke with the user selects * the "New->BuildML->BuildML File" option. */ public NewBmlFile() { super(); setNeedsProgressMonitor(true); } /*=====================================================================================* * PUBLIC METHODS *=====================================================================================*/ /** * Add the single wizard page to this wizard. */ @Override public void addPages() { page = new NewBmlFilePage(selection); addPage(page); } /*-------------------------------------------------------------------------------------*/ /** * We will accept the selection in the workbench to see if we can initialize from it. * @see IWorkbenchWizard#init(IWorkbench, IStructuredSelection) */ public void init(IWorkbench workbench, IStructuredSelection selection) { this.selection = selection; } /*-------------------------------------------------------------------------------------*/ /** * This method is called when 'Finish' button is pressed in the wizard. We will create * an operation and run it using wizard as execution context. */ public boolean performFinish() { /* * Fetch the "parent container" (project/folder) and the new file name that the * user entered in the wizard page. */ final String containerName = page.getContainerName(); final String fileName = page.getFileName(); IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IResource resource = root.findMember(new Path(containerName)); if ((resource == null) || !resource.exists() || !(resource instanceof IContainer)) { AlertDialog.displayErrorDialog("Error", "Parent project/folder \"" + containerName + "\" does not exist."); } /* check that the file doesn't already exist */ IContainer container = (IContainer) resource; final IFile file = container.getFile(new Path(fileName)); if (file.exists()) { AlertDialog.displayErrorDialog("Error", "The BuildML file " + fileName + " already exists."); } /* try to create the file, as a new BuildStore database. */ IPath location = file.getLocation(); if (location != null) { try { String fullPath = location.toOSString(); IBuildStore bs = BuildStoreFactory.createBuildStore(fullPath); configureWorkspace(bs, fullPath); bs.close(); } catch (FileNotFoundException e) { AlertDialog.displayErrorDialog("Error", "A problem occurred while creating the new file: " + fileName); } catch (IOException e) { AlertDialog.displayErrorDialog("Error", "A I/O error occurred while creating the new file: " + fileName); } catch (BuildStoreVersionException e) { AlertDialog.displayErrorDialog("Error", "BuildML file has an incompatible version: " + fileName); } } /* refresh the container, so the new file appears in the package explorer */ try { container.refreshLocal(1, null); } catch (CoreException e1) { /* empty */ } /* * Open the new file in an appropriate editor. */ getShell().getDisplay().asyncExec(new Runnable() { public void run() { IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); try { IDE.openEditor(page, file, true); } catch (PartInitException e) { } } }); return true; } /*-------------------------------------------------------------------------------------*/ /** * Configure the newly-created BuildStore with the workspace root. * @param buildStore The newly-created BuildStore. * @param fullPath Path to the BuildML database file. */ private void configureWorkspace(IBuildStore buildStore, String fullPath) { /* Set the "workspace" root in the FileMgr */ String workspaceRootNative = EclipsePartUtils.workspaceRelativeToAbsolutePath(""); IFileMgr fileMgr = buildStore.getFileMgr(); IPackageRootMgr pkgRootMgr = buildStore.getPackageRootMgr(); int workspaceRootId = fileMgr.addDirectory(workspaceRootNative); if ((workspaceRootId == ErrorCode.BAD_PATH) || (pkgRootMgr.setWorkspaceRoot(workspaceRootId) != ErrorCode.OK)) { throw new FatalBuildScannerError("Unable to set workspace root"); } /* Compute and set the depth of the build.ml file within the workspace */ if (!fullPath.startsWith(workspaceRootNative + "/")) { throw new FatalBuildScannerError("Can not save file outside of workspace"); } int newDepth = 0; File parentFile = new File(fullPath).getParentFile(); while (!(parentFile.toString().equals(workspaceRootNative))) { parentFile = parentFile.getParentFile(); newDepth++; } pkgRootMgr.setBuildMLFileDepth(newDepth); } /*-------------------------------------------------------------------------------------*/ }