Bug #1248155: avoid NPE in parser
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / wizards / PHPFileWizard.java
1 package net.sourceforge.phpeclipse.wizards;
2
3 /**********************************************************************
4  Copyright (c) 2000, 2002 IBM Corp. and others.
5  All rights reserved. This program and the accompanying materials
6  are made available under the terms of the Common Public License v1.0
7  which accompanies this distribution, and is available at
8  http://www.eclipse.org/legal/cpl-v10.html
9
10  Contributors:
11  IBM Corporation - Initial implementation
12  www.phpeclipse.de
13  **********************************************************************/
14
15 import java.io.ByteArrayInputStream;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.lang.reflect.InvocationTargetException;
19
20 import net.sourceforge.phpdt.internal.corext.codemanipulation.StubUtility;
21 import net.sourceforge.phpdt.internal.corext.template.php.CodeTemplateContext;
22 import net.sourceforge.phpdt.internal.corext.template.php.CodeTemplateContextType;
23 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
24
25 import org.eclipse.core.resources.IContainer;
26 import org.eclipse.core.resources.IFile;
27 import org.eclipse.core.resources.IResource;
28 import org.eclipse.core.resources.IWorkspaceRoot;
29 import org.eclipse.core.resources.ResourcesPlugin;
30 import org.eclipse.core.runtime.CoreException;
31 import org.eclipse.core.runtime.IProgressMonitor;
32 import org.eclipse.core.runtime.IStatus;
33 import org.eclipse.core.runtime.Path;
34 import org.eclipse.core.runtime.Status;
35 import org.eclipse.jface.dialogs.MessageDialog;
36 import org.eclipse.jface.operation.IRunnableWithProgress;
37 import org.eclipse.jface.text.templates.Template;
38 import org.eclipse.jface.viewers.ISelection;
39 import org.eclipse.jface.viewers.IStructuredSelection;
40 import org.eclipse.jface.wizard.Wizard;
41 import org.eclipse.ui.INewWizard;
42 import org.eclipse.ui.IWorkbench;
43 import org.eclipse.ui.IWorkbenchPage;
44 import org.eclipse.ui.IWorkbenchWizard;
45 import org.eclipse.ui.PartInitException;
46 import org.eclipse.ui.PlatformUI;
47 import org.eclipse.ui.ide.IDE;
48
49 /**
50  * This wizard creates one file with the extension "php".
51  */
52 public class PHPFileWizard extends Wizard implements INewWizard {
53
54   private PHPFileWizardPage page;
55
56   private ISelection selection;
57
58   // the name of the file to create
59   private String fFileName;
60
61   public PHPFileWizard() {
62     super();
63     setNeedsProgressMonitor(true);
64   }
65
66   /**
67    * Adding the page to the wizard.
68    */
69   public void addPages() {
70     page = new PHPFileWizardPage(selection);
71     addPage(page);
72   }
73
74   /**
75    * This method is called when 'Finish' button is pressed in the wizard. We will create an operation and run it using wizard as
76    * execution context.
77    */
78   public boolean performFinish() {
79     final String containerName = page.getContainerName();
80     final String fileName = page.getFileName();
81     IRunnableWithProgress op = new IRunnableWithProgress() {
82       public void run(IProgressMonitor monitor) throws InvocationTargetException {
83         try {
84           doFinish(containerName, fileName, monitor);
85         } catch (CoreException e) {
86           throw new InvocationTargetException(e);
87         } finally {
88           monitor.done();
89         }
90       }
91     };
92     try {
93       getContainer().run(true, false, op);
94     } catch (InterruptedException e) {
95       return false;
96     } catch (InvocationTargetException e) {
97       Throwable realException = e.getTargetException();
98       MessageDialog.openError(getShell(), PHPWizardMessages.getString("Wizard.error"), realException.getMessage());
99       return false;
100     }
101     return true;
102   }
103
104   /**
105    * The worker method. It will find the container, create the file if missing or just replace its contents, and open the editor on
106    * the newly created file.
107    */
108   private void doFinish(String containerName, String fileName, IProgressMonitor monitor) throws CoreException {
109     // create a sample file
110     monitor.beginTask(PHPWizardMessages.getString("Wizard.Monitor.creating") + " " + fileName, 2);
111     IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
112     IResource resource = root.findMember(new Path(containerName));
113     if (!resource.exists() || !(resource instanceof IContainer)) {
114       throwCoreException(PHPWizardMessages.getString("Wizard.Monitor.containerDoesNotExistException"));
115     }
116     IContainer container = (IContainer) resource;
117     final IFile file = container.getFile(new Path(fileName));
118     String className = getClassName(fileName);
119
120     try {
121       InputStream stream;
122       if (className == null) {
123         stream = openContentStream(fileName);
124       } else {
125         stream = openContentStreamClass(className);
126       }
127       if (file.exists()) {
128         file.setContents(stream, true, true, monitor);
129       } else {
130         file.create(stream, true, monitor);
131       }
132       stream.close();
133     } catch (IOException e) {
134     }
135     monitor.worked(1);
136     monitor.setTaskName(PHPWizardMessages.getString("Wizard.Monitor.openingFile"));
137     getShell().getDisplay().asyncExec(new Runnable() {
138       public void run() {
139         IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
140         try {
141           IDE.openEditor(page, file, true);
142         } catch (PartInitException e) {
143         }
144       }
145     });
146     monitor.worked(1);
147   }
148
149   /**
150    * Check if the filename is like this anyname.class.php
151    * 
152    * @param fFileName
153    *          the filename
154    * @return the anyname or null
155    */
156   private static final String getClassName(final String fileName) {
157     final int lastDot = fileName.lastIndexOf('.');
158     if (lastDot == -1)
159       return null;
160     final int precLastDot = fileName.lastIndexOf('.', lastDot - 1);
161     if (precLastDot == -1)
162       return null;
163     if (!fileName.substring(precLastDot + 1, lastDot).toUpperCase().equals("CLASS"))
164       return null;
165     return fileName.substring(0, precLastDot);
166   }
167
168   /**
169    * We will initialize file contents for a class
170    * 
171    * @param className
172    *          the classname
173    */
174   private InputStream openContentStreamClass(final String className) {
175     StringBuffer contents = new StringBuffer("<?php\n\n");
176     contents.append("class ");
177     contents.append(className);
178     contents.append(" {\n\n");
179     contents.append("    function ");
180     contents.append(className);
181     contents.append("() {\n");
182     contents.append("    }\n}\n?>");
183     return new ByteArrayInputStream(contents.toString().getBytes());
184   }
185
186   /**
187    * We will initialize file contents with a sample text.
188    */
189   private InputStream openContentStream(String fileName) {
190     try {
191       Template template = PHPeclipsePlugin.getDefault().getCodeTemplateStore().findTemplate(CodeTemplateContextType.NEWTYPE);
192       if (template == null) {
193         return null;
194       }
195       String lineDelimiter = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
196       CodeTemplateContext context = new CodeTemplateContext(template.getContextTypeId(), null, lineDelimiter);
197       context.setFileNameVariable(fileName);
198       return new ByteArrayInputStream(StubUtility.evaluateTemplate(context, template).getBytes());
199     } catch (CoreException e) {
200       e.printStackTrace();
201       return null;
202     }
203
204   }
205
206   private void throwCoreException(String message) throws CoreException {
207     IStatus status = new Status(IStatus.ERROR, "net.sourceforge.phpeclipse.wizards", IStatus.OK, message, null);
208     throw new CoreException(status);
209   }
210
211   /**
212    * We will accept the selection in the workbench to see if we can initialize from it.
213    * 
214    * @see IWorkbenchWizard#init(IWorkbench, IStructuredSelection)
215    */
216   public void init(IWorkbench workbench, IStructuredSelection selection) {
217     this.selection = selection;
218   }
219
220   /**
221    * Sets the name of the file to create (used to set the class name in the new file)
222    */
223   public void setFileName(String name) {
224     fFileName = name;
225   }
226 }