001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: * Sebastian Davids <sdavids@gmx.de> bug 38692
011: *******************************************************************************/package org.eclipse.jdt.internal.ui.javadocexport;
012:
013: import java.io.File;
014: import java.io.FileWriter;
015: import java.io.IOException;
016: import java.net.MalformedURLException;
017: import java.net.URL;
018: import java.util.ArrayList;
019: import java.util.Collections;
020: import java.util.List;
021:
022: import org.eclipse.core.runtime.CoreException;
023: import org.eclipse.core.runtime.IPath;
024: import org.eclipse.core.runtime.IStatus;
025: import org.eclipse.core.runtime.Path;
026: import org.eclipse.core.runtime.Status;
027:
028: import org.eclipse.core.resources.IFile;
029: import org.eclipse.core.resources.IResource;
030: import org.eclipse.core.resources.IWorkspaceRoot;
031: import org.eclipse.core.resources.ResourcesPlugin;
032:
033: import org.eclipse.swt.widgets.Display;
034: import org.eclipse.swt.widgets.Shell;
035:
036: import org.eclipse.jface.dialogs.ErrorDialog;
037: import org.eclipse.jface.dialogs.IDialogConstants;
038: import org.eclipse.jface.dialogs.MessageDialog;
039: import org.eclipse.jface.resource.JFaceResources;
040: import org.eclipse.jface.viewers.ISelection;
041: import org.eclipse.jface.viewers.IStructuredSelection;
042: import org.eclipse.jface.wizard.IWizardPage;
043: import org.eclipse.jface.wizard.Wizard;
044: import org.eclipse.jface.wizard.WizardDialog;
045:
046: import org.eclipse.ui.IExportWizard;
047: import org.eclipse.ui.IWorkbench;
048: import org.eclipse.ui.IWorkbenchWindow;
049: import org.eclipse.ui.PlatformUI;
050:
051: import org.eclipse.debug.core.DebugEvent;
052: import org.eclipse.debug.core.DebugPlugin;
053: import org.eclipse.debug.core.IDebugEventSetListener;
054: import org.eclipse.debug.core.ILaunch;
055: import org.eclipse.debug.core.ILaunchConfigurationType;
056: import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
057: import org.eclipse.debug.core.ILaunchManager;
058: import org.eclipse.debug.core.Launch;
059: import org.eclipse.debug.core.model.IProcess;
060:
061: import org.eclipse.debug.ui.IDebugUIConstants;
062:
063: import org.eclipse.jdt.core.IJavaElement;
064: import org.eclipse.jdt.core.IJavaProject;
065:
066: import org.eclipse.jdt.internal.corext.util.Messages;
067:
068: import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
069:
070: import org.eclipse.jdt.ui.JavaUI;
071:
072: import org.eclipse.jdt.internal.ui.JavaPlugin;
073: import org.eclipse.jdt.internal.ui.JavaPluginImages;
074: import org.eclipse.jdt.internal.ui.actions.OpenBrowserUtil;
075: import org.eclipse.jdt.internal.ui.dialogs.OptionalMessageDialog;
076: import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
077: import org.eclipse.jdt.internal.ui.refactoring.RefactoringSaveHelper;
078: import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
079: import org.eclipse.jdt.internal.ui.util.PixelConverter;
080:
081: import org.w3c.dom.Element;
082:
083: public class JavadocWizard extends Wizard implements IExportWizard {
084:
085: private JavadocTreeWizardPage fTreeWizardPage;
086: private JavadocSpecificsWizardPage fLastWizardPage;
087: private JavadocStandardWizardPage fStandardDocletWizardPage;
088: private ContributedJavadocWizardPage[] fContributedJavadocWizardPages;
089:
090: private IPath fDestination;
091:
092: private boolean fWriteCustom;
093: private boolean fOpenInBrowser;
094:
095: private final String TREE_PAGE_DESC = "JavadocTreePage"; //$NON-NLS-1$
096: private final String SPECIFICS_PAGE_DESC = "JavadocSpecificsPage"; //$NON-NLS-1$
097: private final String STANDARD_PAGE_DESC = "JavadocStandardPage"; //$NON-NLS-1$
098:
099: private final int YES = 0;
100: private final int YES_TO_ALL = 1;
101: private final int NO = 2;
102: private final int NO_TO_ALL = 3;
103: private final String JAVADOC_ANT_INFORMATION_DIALOG = "javadocAntInformationDialog";//$NON-NLS-1$
104:
105: private JavadocOptionsManager fStore;
106: private IWorkspaceRoot fRoot;
107:
108: private IFile fXmlJavadocFile;
109:
110: private static final String ID_JAVADOC_PROCESS_TYPE = "org.eclipse.jdt.ui.javadocProcess"; //$NON-NLS-1$
111:
112: public static void openJavadocWizard(JavadocWizard wizard,
113: Shell shell, IStructuredSelection selection) {
114: wizard.init(PlatformUI.getWorkbench(), selection);
115:
116: WizardDialog dialog = new WizardDialog(shell, wizard);
117: PixelConverter converter = new PixelConverter(JFaceResources
118: .getDialogFont());
119: dialog.setMinimumPageSize(converter
120: .convertWidthInCharsToPixels(100), converter
121: .convertHeightInCharsToPixels(20));
122: dialog.open();
123: }
124:
125: public JavadocWizard() {
126: this (null);
127: }
128:
129: public JavadocWizard(IFile xmlJavadocFile) {
130: super ();
131: setDefaultPageImageDescriptor(JavaPluginImages.DESC_WIZBAN_EXPORT_JAVADOC);
132: setWindowTitle(JavadocExportMessages.JavadocWizard_javadocwizard_title);
133:
134: setDialogSettings(JavaPlugin.getDefault().getDialogSettings());
135:
136: fRoot = ResourcesPlugin.getWorkspace().getRoot();
137: fXmlJavadocFile = xmlJavadocFile;
138:
139: fWriteCustom = false;
140: }
141:
142: /*
143: * @see IWizard#performFinish()
144: */
145: public boolean performFinish() {
146: updateStore();
147:
148: IJavaProject[] checkedProjects = fTreeWizardPage
149: .getCheckedProjects();
150: fStore.updateDialogSettings(getDialogSettings(),
151: checkedProjects);
152:
153: // Wizard should not run with dirty editors
154: if (!new RefactoringSaveHelper(
155: RefactoringSaveHelper.SAVE_ALL_ALWAYS_ASK)
156: .saveEditors(getShell())) {
157: return false;
158: }
159:
160: fDestination = Path.fromOSString(fStore.getDestination());
161: fDestination.toFile().mkdirs();
162:
163: fOpenInBrowser = fStore.doOpenInBrowser();
164:
165: //Ask if you wish to set the javadoc location for the projects (all) to
166: //the location of the newly generated javadoc
167: if (fStore.isFromStandard()) {
168: try {
169:
170: URL newURL = fDestination.toFile().toURL();
171: List projs = new ArrayList();
172: //get javadoc locations for all projects
173: for (int i = 0; i < checkedProjects.length; i++) {
174: IJavaProject curr = checkedProjects[i];
175: URL currURL = JavaUI
176: .getProjectJavadocLocation(curr);
177: if (!newURL.equals(currURL)) { // currURL can be null
178: //if not all projects have the same javadoc location ask if you want to change
179: //them to have the same javadoc location
180: projs.add(curr);
181: }
182: }
183: if (!projs.isEmpty()) {
184: setAllJavadocLocations((IJavaProject[]) projs
185: .toArray(new IJavaProject[projs.size()]),
186: newURL);
187: }
188: } catch (MalformedURLException e) {
189: JavaPlugin.log(e);
190: }
191: }
192:
193: if (fLastWizardPage.generateAnt()) {
194: //@Improve: make a better message
195: OptionalMessageDialog
196: .open(
197: JAVADOC_ANT_INFORMATION_DIALOG,
198: getShell(),
199: JavadocExportMessages.JavadocWizard_antInformationDialog_title,
200: null,
201: JavadocExportMessages.JavadocWizard_antInformationDialog_message,
202: MessageDialog.INFORMATION,
203: new String[] { IDialogConstants.OK_LABEL },
204: 0);
205: try {
206: Element javadocXMLElement = fStore
207: .createXML(checkedProjects);
208: if (javadocXMLElement != null) {
209:
210: if (!fTreeWizardPage.getCustom()) {
211: for (int i = 0; i < fContributedJavadocWizardPages.length; i++) {
212: fContributedJavadocWizardPages[i]
213: .updateAntScript(javadocXMLElement);
214: }
215: }
216: File file = fStore.writeXML(javadocXMLElement);
217: IFile[] files = fRoot.findFilesForLocation(Path
218: .fromOSString(file.getPath()));
219: if (files != null) {
220: for (int i = 0; i < files.length; i++) {
221: files[i].refreshLocal(IResource.DEPTH_ONE,
222: null);
223: }
224: }
225: }
226:
227: } catch (CoreException e) {
228: ExceptionHandler
229: .handle(
230: e,
231: getShell(),
232: JavadocExportMessages.JavadocWizard_error_writeANT_title,
233: JavadocExportMessages.JavadocWizard_error_writeANT_message);
234: }
235: }
236:
237: if (!executeJavadocGeneration())
238: return false;
239:
240: return true;
241: }
242:
243: private void updateStore() {
244: fTreeWizardPage.updateStore();
245: if (!fTreeWizardPage.getCustom())
246: fStandardDocletWizardPage.updateStore();
247: fLastWizardPage.updateStore();
248: }
249:
250: /* (non-Javadoc)
251: * @see org.eclipse.jface.wizard.IWizard#performCancel()
252: */
253: public boolean performCancel() {
254: updateStore();
255:
256: //If the wizard was not launched from an ant file store the settings
257: if (fXmlJavadocFile == null) {
258: IJavaProject[] checkedProjects = fTreeWizardPage
259: .getCheckedProjects();
260: fStore.updateDialogSettings(getDialogSettings(),
261: checkedProjects);
262: }
263: return super .performCancel();
264: }
265:
266: private void setAllJavadocLocations(IJavaProject[] projects,
267: URL newURL) {
268: Shell shell = getShell();
269: String[] buttonlabels = new String[] {
270: IDialogConstants.YES_LABEL,
271: IDialogConstants.YES_TO_ALL_LABEL,
272: IDialogConstants.NO_LABEL,
273: IDialogConstants.NO_TO_ALL_LABEL };
274:
275: for (int j = 0; j < projects.length; j++) {
276: IJavaProject iJavaProject = projects[j];
277: String message = Messages
278: .format(
279: JavadocExportMessages.JavadocWizard_updatejavadoclocation_message,
280: new String[] {
281: iJavaProject.getElementName(),
282: fDestination.toOSString() });
283: MessageDialog dialog = new MessageDialog(
284: shell,
285: JavadocExportMessages.JavadocWizard_updatejavadocdialog_label,
286: null, message, MessageDialog.QUESTION,
287: buttonlabels, 1);
288:
289: switch (dialog.open()) {
290: case YES:
291: JavaUI.setProjectJavadocLocation(iJavaProject, newURL);
292: break;
293: case YES_TO_ALL:
294: for (int i = j; i < projects.length; i++) {
295: iJavaProject = projects[i];
296: JavaUI.setProjectJavadocLocation(iJavaProject,
297: newURL);
298: j++;
299: }
300: break;
301: case NO_TO_ALL:
302: j = projects.length;
303: break;
304: case NO:
305: default:
306: break;
307: }
308: }
309: }
310:
311: private boolean executeJavadocGeneration() {
312: Process process = null;
313: try {
314: ArrayList vmArgs = new ArrayList();
315: ArrayList progArgs = new ArrayList();
316:
317: IStatus status = fStore.getArgumentArray(vmArgs, vmArgs);
318: if (!status.isOK()) {
319: ErrorDialog
320: .openError(
321: getShell(),
322: JavadocExportMessages.JavadocWizard_error_title,
323: JavadocExportMessages.JavadocWizard_warning_starting_message,
324: status);
325: }
326:
327: if (!fTreeWizardPage.getCustom()) {
328: for (int i = 0; i < fContributedJavadocWizardPages.length; i++) {
329: fContributedJavadocWizardPages[i].updateArguments(
330: vmArgs, vmArgs);
331: }
332: }
333:
334: File file = File
335: .createTempFile("javadoc-arguments", ".tmp"); //$NON-NLS-1$//$NON-NLS-2$
336: vmArgs.add('@' + file.getAbsolutePath());
337:
338: FileWriter writer = new FileWriter(file);
339: try {
340: for (int i = 0; i < progArgs.size(); i++) {
341: String curr = (String) progArgs.get(i);
342: curr = checkForSpaces(curr);
343:
344: writer.write(curr);
345: writer.write(' ');
346: }
347: } finally {
348: writer.close();
349: }
350:
351: String[] args = (String[]) vmArgs.toArray(new String[vmArgs
352: .size()]);
353: process = Runtime.getRuntime().exec(args);
354: if (process != null) {
355: // construct a formatted command line for the process properties
356: StringBuffer buf = new StringBuffer();
357: for (int i = 0; i < args.length; i++) {
358: buf.append(args[i]);
359: buf.append(' ');
360: }
361:
362: IDebugEventSetListener listener = new JavadocDebugEventListener(
363: getShell().getDisplay(), file);
364: DebugPlugin.getDefault()
365: .addDebugEventListener(listener);
366:
367: ILaunchConfigurationWorkingCopy wc = null;
368: try {
369: ILaunchConfigurationType lcType = DebugPlugin
370: .getDefault()
371: .getLaunchManager()
372: .getLaunchConfigurationType(
373: IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION);
374: String name = JavadocExportMessages.JavadocWizard_launchconfig_name;
375: wc = lcType.newInstance(null, name);
376: wc.setAttribute(IDebugUIConstants.ATTR_PRIVATE,
377: true);
378:
379: ILaunch newLaunch = new Launch(wc,
380: ILaunchManager.RUN_MODE, null);
381: IProcess iprocess = DebugPlugin
382: .newProcess(
383: newLaunch,
384: process,
385: JavadocExportMessages.JavadocWizard_javadocprocess_label);
386: iprocess.setAttribute(IProcess.ATTR_CMDLINE, buf
387: .toString());
388: iprocess.setAttribute(IProcess.ATTR_PROCESS_TYPE,
389: ID_JAVADOC_PROCESS_TYPE);
390:
391: DebugPlugin.getDefault().getLaunchManager()
392: .addLaunch(newLaunch);
393:
394: } catch (CoreException e) {
395: String title = JavadocExportMessages.JavadocWizard_error_title;
396: String message = JavadocExportMessages.JavadocWizard_launch_error_message;
397: ExceptionHandler.handle(e, getShell(), title,
398: message);
399: }
400:
401: return true;
402:
403: }
404: } catch (IOException e) {
405: String title = JavadocExportMessages.JavadocWizard_error_title;
406: String message = JavadocExportMessages.JavadocWizard_exec_error_message;
407:
408: IStatus status = new Status(IStatus.ERROR,
409: JavaUI.ID_PLUGIN, IStatus.ERROR, e.getMessage(), e);
410: ExceptionHandler.handle(new CoreException(status),
411: getShell(), title, message);
412: return false;
413: }
414: return false;
415:
416: }
417:
418: private String checkForSpaces(String curr) {
419: if (curr.indexOf(' ') == -1) {
420: return curr;
421: }
422: StringBuffer buf = new StringBuffer();
423: buf.append('\'');
424: for (int i = 0; i < curr.length(); i++) {
425: char ch = curr.charAt(i);
426: if (ch == '\\' || ch == '\'') {
427: buf.append('\\');
428: }
429: buf.append(ch);
430: }
431: buf.append('\'');
432: return buf.toString();
433: }
434:
435: /*
436: * @see IWizard#addPages()
437: */
438: public void addPages() {
439: fContributedJavadocWizardPages = ContributedJavadocWizardPage
440: .getContributedPages(fStore);
441:
442: fTreeWizardPage = new JavadocTreeWizardPage(TREE_PAGE_DESC,
443: fStore);
444: fLastWizardPage = new JavadocSpecificsWizardPage(
445: SPECIFICS_PAGE_DESC, fTreeWizardPage, fStore);
446: fStandardDocletWizardPage = new JavadocStandardWizardPage(
447: STANDARD_PAGE_DESC, fTreeWizardPage, fStore);
448:
449: super .addPage(fTreeWizardPage);
450: super .addPage(fStandardDocletWizardPage);
451:
452: for (int i = 0; i < fContributedJavadocWizardPages.length; i++) {
453: super .addPage(fContributedJavadocWizardPages[i]);
454: }
455: super .addPage(fLastWizardPage);
456:
457: fTreeWizardPage.init();
458: fStandardDocletWizardPage.init();
459: fLastWizardPage.init();
460: }
461:
462: public void init(IWorkbench workbench,
463: IStructuredSelection structuredSelection) {
464: IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
465: List selected = Collections.EMPTY_LIST;
466: if (window != null) {
467: ISelection selection = window.getSelectionService()
468: .getSelection();
469: if (selection instanceof IStructuredSelection) {
470: selected = ((IStructuredSelection) selection).toList();
471: } else {
472: IJavaElement element = EditorUtility
473: .getActiveEditorJavaInput();
474: if (element != null) {
475: selected = new ArrayList();
476: selected.add(element);
477: }
478: }
479: }
480: fStore = new JavadocOptionsManager(fXmlJavadocFile,
481: getDialogSettings(), selected);
482: }
483:
484: private void refresh(IPath path) {
485: if (fRoot.findContainersForLocation(path).length > 0) {
486: try {
487: fRoot.refreshLocal(IResource.DEPTH_INFINITE, null);
488: } catch (CoreException e) {
489: JavaPlugin.log(e);
490: }
491: }
492: }
493:
494: private void spawnInBrowser(Display display) {
495: if (fOpenInBrowser) {
496: try {
497: IPath indexFile = fDestination.append("index.html"); //$NON-NLS-1$
498: URL url = indexFile.toFile().toURL();
499: OpenBrowserUtil.open(url, display, getWindowTitle());
500: } catch (MalformedURLException e) {
501: JavaPlugin.log(e);
502: }
503: }
504: }
505:
506: private class JavadocDebugEventListener implements
507: IDebugEventSetListener {
508: private Display fDisplay;
509: private File fFile;
510:
511: public JavadocDebugEventListener(Display display, File file) {
512: fDisplay = display;
513: fFile = file;
514: }
515:
516: public void handleDebugEvents(DebugEvent[] events) {
517: for (int i = 0; i < events.length; i++) {
518: if (events[i].getKind() == DebugEvent.TERMINATE) {
519: try {
520: if (!fWriteCustom) {
521: fFile.delete();
522: refresh(fDestination); //If destination of javadoc is in workspace then refresh workspace
523: spawnInBrowser(fDisplay);
524: }
525: } finally {
526: DebugPlugin.getDefault()
527: .removeDebugEventListener(this );
528: }
529: return;
530: }
531: }
532: }
533: }
534:
535: public IWizardPage getNextPage(IWizardPage page) {
536: if (page == fTreeWizardPage && fTreeWizardPage.getCustom()) {
537: return fLastWizardPage;
538: }
539: return super .getNextPage(page);
540: }
541:
542: public IWizardPage getPreviousPage(IWizardPage page) {
543: if (page == fLastWizardPage && fTreeWizardPage.getCustom()) {
544: return fTreeWizardPage;
545: }
546: return super.getPreviousPage(page);
547: }
548:
549: }
|