package org.maziarz.yiiclipse.wizards;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IProject;
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.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IAccessRule;
import org.eclipse.dltk.core.IBuildpathAttribute;
import org.eclipse.dltk.core.IBuildpathEntry;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.IOverwriteQuery;
import org.eclipse.ui.wizards.datatransfer.ImportOperation;
import org.maziarz.yiiclipse.YiiclipseBundle;
import org.maziarz.yiiclipse.datatransfer.TarEntry;
import org.maziarz.yiiclipse.datatransfer.TarException;
import org.maziarz.yiiclipse.datatransfer.TarFile;
import org.maziarz.yiiclipse.datatransfer.TarHandler;
import org.maziarz.yiiclipse.preferences.YiiclipsePreferenceConstants;
public class WizardNewYiiProjectConfigurationPage extends WizardPage implements IOverwriteQuery {
private String frameworkLocation;
protected WizardNewYiiProjectConfigurationPage(String pageName) {
super(pageName);
yiiVersionSizes.put("yii-1.1.13-RC.0f7bee", "3921070");
yiiVersionSizes.put("yii-1.1.12.b600af", "3829049");
yiiVersionSizes.put("yii-1.1.11.58da45", "3829033");
yiiVersionSizes.put("yii-1.0.12.r1898", "1898464");
}
public String getFrameworkLocation() {
return frameworkLocation;
}
private Map<Button, String> yiiVersionButtons;
Map<String, String> yiiVersionSizes = new HashMap<String, String>();
private boolean isDownloadRequired;
private Map<Button, String> yiiApplication;
private Text downloadDestination;
private File tmpDownloadedFile;
private Button removeYiiliteButton;
private String errorMessage;
@Override
public void createControl(Composite parent) {
Composite container = new Composite(parent, SWT.None);
initializeDialogUnits(parent);
container.setLayout(new GridLayout());
final Group group = new Group(container, SWT.None);
group.setLayoutData(new GridData(GridData.FILL_BOTH));
group.setLayout(new GridLayout(3, false));
group.setText("Yii framework location");
final Button useLocalButton = new Button(group, SWT.RADIO);
useLocalButton.setText("Use local");
GridData gData = new GridData();
gData.horizontalSpan = 3;
useLocalButton.setLayoutData(gData);
useLocalButton.setSelection(true);
final Label localDirLabel = new Label(group, SWT.NONE);
localDirLabel.setText("Path: ");
final Text localDirText = new Text(group, SWT.BORDER);
localDirText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
localDirText.setEditable(false);
final Button localSelectDir = new Button(group, SWT.PUSH);
localSelectDir.setText("Browse");
final IPreferenceStore preferences = YiiclipseBundle.getDefault().getPreferenceStore();
final String defaultLoc = preferences.getString(YiiclipsePreferenceConstants.FRAMEWORK_PATH);
if (defaultLoc.isEmpty() == false) {
localDirText.setText(defaultLoc);
frameworkLocation = defaultLoc;
}
localSelectDir.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
DirectoryDialog directoryDialog = new DirectoryDialog(group.getShell());
directoryDialog.setText("Choose location of yii framework copy.");
directoryDialog.setFilterPath(defaultLoc);
directoryDialog.setMessage("Please select a directory and click OK");
String dir = directoryDialog.open();
if (dir != null) {
preferences.putValue(YiiclipsePreferenceConstants.FRAMEWORK_PATH, dir);
localDirText.setText(dir);
frameworkLocation = dir;
YiiclipseBundle.debug("LocalSelectDir: " + dir);
}
}
});
final Button downloadButton = new Button(group, SWT.RADIO);
downloadButton.setText("Download");
gData = new GridData();
gData.horizontalSpan = 3;
downloadButton.setLayoutData(gData);
downloadButton.setEnabled(true);
final Group chooseVersionGroup = new Group(group, SWT.None);
gData = new GridData(SWT.FILL, SWT.None, true, false);
gData.horizontalSpan = 3;
chooseVersionGroup.setLayoutData(gData);
chooseVersionGroup.setLayout(new RowLayout());
chooseVersionGroup.setText("Yii Framework version");
yiiVersionButtons = new HashMap<Button, String>();
final Button version11Dev = new Button(chooseVersionGroup, SWT.RADIO);
version11Dev.setText("1.1.13-RC");
yiiVersionButtons.put(version11Dev, "yii-1.1.13-RC.0f7bee");
final Button version117 = new Button(chooseVersionGroup, SWT.RADIO);
version117.setText("1.1.12");
version117.setSelection(true);
yiiVersionButtons.put(version117, "yii-1.1.12.b600af");
final Button version116 = new Button(chooseVersionGroup, SWT.RADIO);
version116.setText("1.1.11");
yiiVersionButtons.put(version116, "yii-1.1.11.58da45");
final Button version1012 = new Button(chooseVersionGroup, SWT.RADIO);
version1012.setText("1.0.12");
yiiVersionButtons.put(version1012, "yii-1.0.12.r1898");
final Label destDirLabel = new Label(group, SWT.NONE);
destDirLabel.setText("Extract to: ");
final Text destDirText = new Text(group, SWT.BORDER);
downloadDestination = destDirText;
destDirText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
validatePage();
}
});
destDirText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
final Button destSelectDir = new Button(group, SWT.PUSH);
destSelectDir.setText("Browse");
if (defaultLoc.isEmpty() == false) {
destDirText.setText(defaultLoc);
frameworkLocation = defaultLoc;
}
destSelectDir.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
DirectoryDialog directoryDialog = new DirectoryDialog(group.getShell());
directoryDialog.setFilterPath(frameworkLocation);
directoryDialog.setMessage("Please select a directory where framework will be extracted.");
String dir = directoryDialog.open();
if (dir != null) {
preferences.putValue(YiiclipsePreferenceConstants.FRAMEWORK_PATH, dir);
destDirText.setText(dir);
frameworkLocation = dir;
YiiclipseBundle.debug("DestSelectDir: " + dir);
}
}
});
removeYiiliteButton = new Button(group, SWT.CHECK);
removeYiiliteButton.setText("Remove yiilite.php file from buildpath");
removeYiiliteButton.setToolTipText("Phisically deletes yiilite.php from downloaded framework.");
removeYiiliteButton.setSelection(true);
GridData layoutData = new GridData(GridData.GRAB_HORIZONTAL);
layoutData.horizontalSpan = 3;
removeYiiliteButton.setLayoutData(layoutData);
final Group chooseApplicationGroup = new Group(container, SWT.None);
gData = new GridData(SWT.FILL, SWT.None, true, false);
gData.horizontalSpan = 3;
chooseApplicationGroup.setLayoutData(gData);
chooseApplicationGroup.setLayout(new RowLayout());
chooseApplicationGroup.setText("Initialize project with");
yiiApplication = new HashMap<Button, String>();
final Button yiiAppNone = new Button(chooseApplicationGroup, SWT.RADIO);
yiiAppNone.setText("None");
yiiApplication.put(yiiAppNone, "none");
final Button yiiAppHelloWorld = new Button(chooseApplicationGroup, SWT.RADIO);
yiiAppHelloWorld.setText("Hello World");
yiiAppHelloWorld.setSelection(true);
yiiApplication.put(yiiAppHelloWorld, "helloworld");
final Button yiiAppBlog = new Button(chooseApplicationGroup, SWT.RADIO);
yiiAppBlog.setText("Blog");
yiiApplication.put(yiiAppBlog, "blog");
final Button yiiAppHangman = new Button(chooseApplicationGroup, SWT.RADIO);
yiiAppHangman.setText("Hangman");
yiiApplication.put(yiiAppHangman, "hangman");
final Button yiiAppPhonebook = new Button(chooseApplicationGroup, SWT.RADIO);
yiiAppPhonebook.setText("Phonebook");
yiiApplication.put(yiiAppPhonebook, "phonebook");
downloadButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e) {
chooseVersionGroup.setEnabled(true);
version11Dev.setEnabled(true);
version117.setEnabled(true);
version116.setEnabled(true);
version1012.setEnabled(true);
destDirLabel.setEnabled(true);
destDirText.setEnabled(true);
destSelectDir.setEnabled(true);
removeYiiliteButton.setEnabled(true);
localDirLabel.setEnabled(false);
localDirText.setEnabled(false);
localSelectDir.setEnabled(false);
toogleGroup(chooseApplicationGroup, true);
isDownloadRequired = true;
validatePage();
}
});
useLocalButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e) {
chooseVersionGroup.setEnabled(false);
version11Dev.setEnabled(false);
version117.setEnabled(false);
version116.setEnabled(false);
version1012.setEnabled(false);
destDirLabel.setEnabled(false);
destDirText.setEnabled(false);
destSelectDir.setEnabled(false);
removeYiiliteButton.setEnabled(false);
localDirLabel.setEnabled(true);
localDirText.setEnabled(true);
localSelectDir.setEnabled(true);
toogleGroup(chooseApplicationGroup, false);
isDownloadRequired = false;
validatePage();
}
});
chooseVersionGroup.setEnabled(false);
version11Dev.setEnabled(false);
version117.setEnabled(false);
version116.setEnabled(false);
version1012.setEnabled(false);
destDirLabel.setEnabled(false);
destDirText.setEnabled(false);
destSelectDir.setEnabled(false);
removeYiiliteButton.setEnabled(false);
localDirLabel.setEnabled(true);
localDirText.setEnabled(true);
localSelectDir.setEnabled(true);
toogleGroup(chooseApplicationGroup, false);
// Assign form to the wizard page
setControl(container);
Dialog.applyDialogFont(container);
setPageComplete(validatePage());
}
private void toogleGroup(Group containerGroup, boolean isEnable) {
for (Control c : containerGroup.getChildren()) {
c.setEnabled(isEnable);
}
containerGroup.setEnabled(isEnable);
}
protected boolean validatePage() {
boolean result = true;
if (this.isDownloadRequired()) {
// String test = downloadDestination.getText();
if (downloadDestination != null && downloadDestination.getText().isEmpty()) {
setErrorMessage("Extracting target location have to be set.");
result = false;
} else if (new File(downloadDestination.getText()).exists() == false) {
setErrorMessage("Extracting target location must be exist.");
result = false;
} else if (new File(downloadDestination.getText()).isDirectory() == false) {
setErrorMessage("Extracting target location must be valid directory.");
result = false;
} else {
setErrorMessage(null);
result = true;
}
} else {
setErrorMessage(null);
}
setPageComplete(result);
return result;
}
public boolean isDownloadRequired() {
return this.isDownloadRequired;
}
public String getVersionForDownload() {
for (Entry<Button, String> entry : yiiVersionButtons.entrySet()) {
if (entry.getKey().getSelection()) {
return entry.getValue();
}
}
return null;
}
public String getApplicationToBeInstalled() {
for (Entry<Button, String> entry : yiiApplication.entrySet()) {
if (entry.getKey().getSelection()) {
return entry.getValue();
}
}
return null;
}
public void performFinish(IProject project) {
String targetLocation = this.getFrameworkLocation();
/**
* Add yii framework location to the project
*/
boolean isFrameworkReady = false;
if (this.isDownloadRequired()) {
final String version = this.getVersionForDownload();
try {
tmpDownloadedFile = File.createTempFile("yii-", ".tar.gz");
tmpDownloadedFile.deleteOnExit();
IRunnableWithProgress downloadOperation = new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
monitor.setTaskName("Downloading yii framework");
int total = Integer.parseInt(yiiVersionSizes.get(version));
String urlString = getFrameworkRemoteHost() + version + ".tar.gz";
monitor.beginTask("Downloading file: " + urlString, total);
try {
URL url = new URL(urlString);
YiiclipseBundle.debug("Tmp download location: " + tmpDownloadedFile);
OutputStream outStream = new BufferedOutputStream(new FileOutputStream(tmpDownloadedFile));
URLConnection connection = url.openConnection();
InputStream is = connection.getInputStream();
int byteRead, byteWritten = 0;
byte[] buf = new byte[8196];
while ((byteRead = is.read(buf)) != -1) {
outStream.write(buf, 0, byteRead);
byteWritten += byteRead;
monitor.worked(byteRead);
monitor.subTask(byteWritten / 1000 + "kb downloaded");
}
is.close();
outStream.close();
} catch (MalformedURLException e) {
errorMessage = e.getMessage();
YiiclipseBundle.logError("MalformedURLException: " + e.getMessage(), e);
} catch (IOException e) {
errorMessage = e.getMessage();
YiiclipseBundle.logError(e.getMessage(), e);
}
}
};
try {
getContainer().run(true, true, downloadOperation);
} catch (InvocationTargetException e) {
Throwable t = e.getTargetException();
if (t instanceof ExecutionException && t.getCause() instanceof CoreException) {
YiiclipseBundle.logError("Downloading yii framework: wielka dupa: " + e.getMessage());
}
} catch (InterruptedException e) {
}
// Extract framework folder
TarFile yiiTarArchive = new TarFile(tmpDownloadedFile);
TarHandler th = new TarHandler(yiiTarArchive);
TarEntry frameworkEntry = th.getEntry(version + "/framework/");
File destFolder = new File(targetLocation);
for (TarEntry entry : th.getChildren(frameworkEntry)) {
th.extractRecursively(entry, destFolder);
}
yiiTarArchive.close();
if (removeYiiliteButton.getSelection()) {
File yiilite = new File(destFolder.getCanonicalPath() + File.separator + "yiilite.php");
if (yiilite.exists()) {
yiilite.delete();
}
}
isFrameworkReady = true;
} catch (IOException e1) {
if (errorMessage == null) {
errorMessage = e1.getMessage();
}
YiiclipseBundle.logError(e1.getMessage());
} catch (TarException e) {
if (errorMessage == null) {
errorMessage = e.getMessage();
}
YiiclipseBundle.logError(e.getMessage());
}
} else {
this.createYiiProjectDirectoryStructure(project);
isFrameworkReady = true;
}
/**
* Add yii framework to the path
*/
if (isFrameworkReady && this.getFrameworkLocation() != null && "".equals(this.getFrameworkLocation()) == false) {
IScriptProject scriptProject = DLTKCore.create(project.getProject());
if (scriptProject != null) {
List<IBuildpathEntry> entries = new LinkedList<IBuildpathEntry>();
IPath yiiFrameworkPath = new Path("org.eclipse.dltk.core.environment.localEnvironment/:",
this.getFrameworkLocation());
IBuildpathEntry entry = DLTKCore.newBuiltinEntry(yiiFrameworkPath, new IAccessRule[0],
new IBuildpathAttribute[0], new IPath[0], new IPath[0], false, true);
entries.add(entry);
try {
IBuildpathEntry[] rawBuildpath = scriptProject.getRawBuildpath();
Set<IBuildpathEntry> newRawBuildpath = new HashSet<IBuildpathEntry>();
for (IBuildpathEntry buildpathEntry : rawBuildpath) {
newRawBuildpath.add(buildpathEntry);
}
for (IBuildpathEntry buildpathEntry : entries) {
newRawBuildpath.add(buildpathEntry);
}
scriptProject.setRawBuildpath(newRawBuildpath.toArray(new IBuildpathEntry[newRawBuildpath.size()]), null);
} catch (ModelException e) {
YiiclipseBundle.logError(e.getMessage(), e);
}
}
} else {
if (errorMessage == null) {
errorMessage = "Framework not found in specified location: " + this.getFrameworkLocation();
}
MessageDialog.openError(getShell(), "Initialization error", " Problem with initializing yii application: "
+ errorMessage);
return;
}
/**
* Install initial application
*/
String application = getApplicationToBeInstalled();
String version = this.getVersionForDownload();
if (this.isDownloadRequired() && !application.equals("none")) {
try {
TarFile yiiTarArchive = new TarFile(tmpDownloadedFile);
TarHandler importStructureProvider = new TarHandler(yiiTarArchive);
TarEntry frameworkEntry = importStructureProvider.getEntry(version + "/demos/" + application + "/");
ImportOperation operation = new ImportOperation(project.getFullPath(), frameworkEntry, importStructureProvider,
this, null);
operation.setContext(getShell());
operation.setCreateContainerStructure(false);
operation.setOverwriteResources(true);
try {
getContainer().run(true, true, operation);
} catch (InterruptedException e) {
} catch (InvocationTargetException e) {
YiiclipseBundle.logError(e.getTargetException().getMessage());
}
IStatus status = operation.getStatus();
if (!status.isOK()) {
ErrorDialog.openError(getContainer().getShell(), "Problem with initializing application", null, status);
}
yiiTarArchive.close();
} catch (Exception e) {
YiiclipseBundle.logError(e.getMessage());
}
}
}
@Override
public String queryOverwrite(String pathString) {
return null;
}
private String getFrameworkRemoteHost() {
String remoteHost = null;
if (System.getProperty("ryfl") != null) {
remoteHost = System.getProperty("ryfl");
if (!remoteHost.endsWith("/")) {
remoteHost += "/";
}
if (!remoteHost.startsWith("http")) {
remoteHost = "file://" + remoteHost;
}
} else {
remoteHost = "http://yii.googlecode.com/files/";
}
YiiclipseBundle.debug("Remote Yii Framework location: " + remoteHost);
return remoteHost;
}
private void createYiiProjectDirectoryStructure(IProject project) {
YiiProjectWorkspaceHelper.INSTANCE.buildBasicProjectStructure(getContainer(), project);
}
}