/** * Copyright 2014 Microsoft Open Technologies Inc. * * Licensed 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 com.microsoftopentechnologies.intellij.serviceexplorer.azure.mobileservice; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.microsoftopentechnologies.intellij.helpers.UIHelper; import com.microsoftopentechnologies.intellij.helpers.azure.AzureCmdException; import com.microsoftopentechnologies.intellij.model.MobileServiceScriptTreeItem; import com.microsoftopentechnologies.intellij.model.Script; import com.microsoftopentechnologies.intellij.model.Service; import com.microsoftopentechnologies.intellij.serviceexplorer.Node; import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.InputStream; public class ScriptNodeBase extends Node { public ScriptNodeBase(String id, String name, Node parent, String iconPath, boolean hasRefreshAction) { super(id, name, parent, iconPath, hasRefreshAction); } protected void downloadScript(Service mobileService, String scriptName, String localFilePath) throws AzureCmdException {} protected void onNodeClickInternal(final MobileServiceScriptTreeItem script) { // TODO: This function is far too long and confusing. Refactor this to smaller well-defined sub-routines. // find the parent MobileServiceNode node MobileServiceNode mobileServiceNode = (MobileServiceNode)findParentByType(MobileServiceNode.class); final Service mobileService = mobileServiceNode.getMobileService(); VirtualFile scriptFile = LocalFileSystem.getInstance().findFileByIoFile(new File(script.getLocalFilePath(mobileService.getName()))); boolean fileIsEditing = false; if (scriptFile != null) fileIsEditing = FileEditorManager.getInstance(getProject()).getEditors(scriptFile).length != 0; if (!fileIsEditing) { try { // mark node as undergoing a "load" setLoading(true); File temppath = new File(script.getLocalDirPath(mobileService.getName())); temppath.mkdirs(); if (script instanceof Script && ((Script) script).getSelfLink() == null) { InputStream is = this.getClass().getResourceAsStream( String.format("/com/microsoftopentechnologies/intellij/templates/%s.js", ((Script) script).getOperation())); final ByteArrayOutputStream buff = new ByteArrayOutputStream(); int b; while ((b = is.read()) != -1) buff.write(b); final File tempf = new File(temppath, ((Script) script).getOperation() + ".js"); tempf.createNewFile(); ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { try { final VirtualFile editfile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(tempf); if (editfile != null) { editfile.setWritable(true); editfile.setBinaryContent(buff.toByteArray()); ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { FileEditorManager.getInstance(getProject()).openFile(editfile, true); } }); } } catch (Throwable e) { UIHelper.showException("Error writing temporal editable file:", e); } finally { setLoading(false); } } }); } else { boolean download = false; final File file = new File(script.getLocalFilePath(mobileService.getName())); if (file.exists()) { String[] options = new String[]{"Use remote", "Use local"}; int optionDialog = JOptionPane.showOptionDialog(null, "There is a local copy of the script. Do you want you replace it with the remote version?", "Edit script", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[1]); if (optionDialog == JOptionPane.YES_OPTION) { download = true; } } else { download = true; } if (download) { ProgressManager.getInstance().run(new Task.Backgroundable(getProject(), "Loading Mobile Services data...", false) { @Override public void run(@NotNull ProgressIndicator progressIndicator) { progressIndicator.setIndeterminate(true); progressIndicator.setText("Downloading script"); try { downloadScript(mobileService, script.getName(), script.getLocalFilePath(mobileService.getName())); final VirtualFile finalEditfile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file); ApplicationManager.getApplication().runReadAction(new Runnable() { @Override public void run() { openFile(finalEditfile, script); } }); } catch (Throwable e) { UIHelper.showException("Error writing temporal editable file:", e); } finally { setLoading(false); } } }); } else { final VirtualFile finalEditfile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file); ApplicationManager.getApplication().runReadAction(new Runnable() { @Override public void run() { try { openFile(finalEditfile, script); } finally { setLoading(false); } } }); } } } catch (Throwable e) { UIHelper.showException("Error writing temporal editable file:", e); setLoading(false); } } } private void openFile(final VirtualFile finalEditfile, MobileServiceScriptTreeItem script) { try { if (finalEditfile != null) { finalEditfile.setWritable(true); ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { FileEditorManager.getInstance(getProject()).openFile(finalEditfile, true); } }); } } catch (Throwable e) { UIHelper.showException("Error writing temporal editable file:", e); } } }