/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.eclipse.servers; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.hadoop.eclipse.Activator; import org.apache.hadoop.eclipse.ErrorMessageDialog; import org.apache.hadoop.eclipse.server.HadoopServer; import org.apache.hadoop.eclipse.server.JarModule; import org.apache.hadoop.mapred.JobConf; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; import org.eclipse.jdt.launching.IRuntimeClasspathEntry; import org.eclipse.jdt.launching.JavaRuntime; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.wizard.Wizard; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; /** * Wizard for publishing a job to a Hadoop server. */ public class RunOnHadoopWizard extends Wizard { private MainWizardPage mainPage; private HadoopLocationWizard createNewPage; /** * The file resource (containing a main()) to run on the Hadoop location */ private IFile resource; /** * The launch configuration to update */ private ILaunchConfigurationWorkingCopy iConf; private IProgressMonitor progressMonitor; public RunOnHadoopWizard(IFile resource, ILaunchConfigurationWorkingCopy iConf) { this.resource = resource; this.iConf = iConf; setForcePreviousAndNextButtons(true); setNeedsProgressMonitor(true); setWindowTitle("Run on Hadoop"); } /** * This wizard contains 2 pages: * <li> the first one lets the user choose an already existing location * <li> the second one allows the user to create a new location, in case it * does not already exist */ /* @inheritDoc */ @Override public void addPages() { addPage(this.mainPage = new MainWizardPage()); addPage(this.createNewPage = new HadoopLocationWizard()); } /** * Performs any actions appropriate in response to the user having pressed * the Finish button, or refuse if finishing now is not permitted. */ /* @inheritDoc */ @Override public boolean performFinish() { /* * Create a new location or get an existing one */ HadoopServer location = null; if (mainPage.createNew.getSelection()) { location = createNewPage.performFinish(); } else if (mainPage.table.getSelection().length == 1) { location = (HadoopServer) mainPage.table.getSelection()[0].getData(); } if (location == null) return false; /* * Get the base directory of the plug-in for storing configurations and * JARs */ File baseDir = Activator.getDefault().getStateLocation().toFile(); // Package the Job into a JAR File jarFile = JarModule.createJarPackage(resource); if (jarFile == null) { ErrorMessageDialog.display("Run on Hadoop", "Unable to create or locate the JAR file for the Job"); return false; } /* * Generate a temporary Hadoop configuration directory and add it to the * classpath of the launch configuration */ File confDir; try { confDir = File.createTempFile("hadoop-conf-", "", baseDir); confDir.delete(); confDir.mkdirs(); if (!confDir.isDirectory()) { ErrorMessageDialog.display("Run on Hadoop", "Cannot create temporary directory: " + confDir); return false; } } catch (IOException ioe) { ioe.printStackTrace(); return false; } // Prepare the Hadoop configuration JobConf conf = new JobConf(location.getConfiguration()); conf.setJar(jarFile.getAbsolutePath()); // Write it to the disk file try { // File confFile = File.createTempFile("hadoop-site-", ".xml", // confDir); File confFile = new File(confDir, "hadoop-site.xml"); FileOutputStream fos = new FileOutputStream(confFile); conf.writeXml(fos); fos.close(); } catch (IOException ioe) { ioe.printStackTrace(); return false; } // Setup the Launch class path List<String> classPath; try { classPath = iConf.getAttribute( IJavaLaunchConfigurationConstants.ATTR_CLASSPATH, new ArrayList()); IPath confIPath = new Path(confDir.getAbsolutePath()); IRuntimeClasspathEntry cpEntry = JavaRuntime.newArchiveRuntimeClasspathEntry(confIPath); classPath.add(0, cpEntry.getMemento()); iConf.setAttribute(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH, classPath); } catch (CoreException e) { e.printStackTrace(); return false; } // location.runResource(resource, progressMonitor); return true; } private void refreshButtons() { getContainer().updateButtons(); } /** * Allows finish when an existing server is selected or when a new server * location is defined */ /* @inheritDoc */ @Override public boolean canFinish() { if (mainPage != null) return mainPage.canFinish(); return false; } /** * This is the main page of the wizard. It allows the user either to choose * an already existing location or to indicate he wants to create a new * location. */ public class MainWizardPage extends WizardPage { private Button createNew; private Table table; private Button chooseExisting; public MainWizardPage() { super("Select or define server to run on"); setTitle("Select Hadoop location"); setDescription("Select a Hadoop location to run on."); } /* @inheritDoc */ @Override public boolean canFlipToNextPage() { return createNew.getSelection(); } /* @inheritDoc */ public void createControl(Composite parent) { Composite panel = new Composite(parent, SWT.NONE); panel.setLayout(new GridLayout(1, false)); // Label Label label = new Label(panel, SWT.NONE); label.setText("Select a Hadoop Server to run on."); GridData gData = new GridData(GridData.FILL_BOTH); gData.grabExcessVerticalSpace = false; label.setLayoutData(gData); // Create location button createNew = new Button(panel, SWT.RADIO); createNew.setText("Define a new Hadoop server location"); createNew.setLayoutData(gData); createNew.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) { setPageComplete(true); RunOnHadoopWizard.this.refreshButtons(); } }); createNew.setSelection(true); // Select existing location button chooseExisting = new Button(panel, SWT.RADIO); chooseExisting .setText("Choose an existing server from the list below"); chooseExisting.setLayoutData(gData); chooseExisting.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) { if (chooseExisting.getSelection() && (table.getSelectionCount() == 0)) { if (table.getItems().length > 0) { table.setSelection(0); } } RunOnHadoopWizard.this.refreshButtons(); } }); // Table of existing locations Composite serverListPanel = new Composite(panel, SWT.FILL); gData = new GridData(GridData.FILL_BOTH); gData.horizontalSpan = 1; serverListPanel.setLayoutData(gData); FillLayout layout = new FillLayout(); layout.marginHeight = layout.marginWidth = 12; serverListPanel.setLayout(layout); table = new Table(serverListPanel, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION); table.setHeaderVisible(true); table.setLinesVisible(true); TableColumn nameColumn = new TableColumn(table, SWT.LEFT); nameColumn.setText("Location"); nameColumn.setWidth(450); TableColumn hostColumn = new TableColumn(table, SWT.LEFT); hostColumn.setText("Master host name"); hostColumn.setWidth(250); // If the user select one entry, switch to "chooseExisting" table.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) { chooseExisting.setSelection(true); createNew.setSelection(false); setPageComplete(table.getSelectionCount() == 1); RunOnHadoopWizard.this.refreshButtons(); } }); TableViewer viewer = new TableViewer(table); HadoopServerSelectionListContentProvider provider = new HadoopServerSelectionListContentProvider(); viewer.setContentProvider(provider); viewer.setLabelProvider(provider); viewer.setInput(new Object()); // don't care, get from singleton server registry this.setControl(panel); } /** * Returns whether this page state allows the Wizard to finish or not * * @return can the wizard finish or not? */ public boolean canFinish() { if (!isControlCreated()) return false; if (this.createNew.getSelection()) return getNextPage().isPageComplete(); return this.chooseExisting.getSelection(); } } /** * @param progressMonitor */ public void setProgressMonitor(IProgressMonitor progressMonitor) { this.progressMonitor = progressMonitor; } }