/** * 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.helpers; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.microsoftopentechnologies.intellij.helpers.azure.AzureCmdException; import sun.misc.IOUtils; import javax.swing.*; import javax.xml.bind.DatatypeConverter; import java.io.*; import java.net.URLDecoder; import java.util.ArrayList; public class AndroidStudioHelper { private static final String mobileServicesTemplateName = "AzureServicesActivity"; private static final String officeTemplateName = "Office365Activity"; public static void newActivityTemplateManager(boolean deleteTemplates, Object caller) throws IOException, InterruptedException { String templatePath = URLDecoder.decode(ApplicationComponent.class.getResource("").getPath().replace("file:/", ""), "UTF-8"); templatePath = templatePath.replace("/", File.separator); templatePath = templatePath.substring(0, templatePath.indexOf(File.separator + "lib")); templatePath = templatePath + File.separator + "plugins" + File.separator + "android" + File.separator; templatePath = templatePath + "lib" + File.separator + "templates" + File.separator + "activities" + File.separator; if (System.getProperty("os.name").toLowerCase().startsWith("mac") && !templatePath.startsWith(File.separator)) { templatePath = File.separator + templatePath; } if (deleteTemplates || !new File(templatePath + mobileServicesTemplateName).exists()) { String tmpDir = getTempLocation(); copyResourcesRecursively(new File(tmpDir)); tmpDir = tmpDir + "MobileServiceTemplate" + File.separator; if (System.getProperty("os.name").toLowerCase().startsWith("windows")) { try { if (deleteTemplates) { VirtualFile mobileTemplate = LocalFileSystem.getInstance().findFileByIoFile(new File(templatePath + mobileServicesTemplateName)); VirtualFile officeTemplate = LocalFileSystem.getInstance().findFileByIoFile(new File(templatePath + officeTemplateName)); if (mobileTemplate != null) mobileTemplate.delete(caller); if (officeTemplate != null) officeTemplate.delete(caller); } copyFolder(new File(tmpDir + mobileServicesTemplateName), new File(templatePath + mobileServicesTemplateName)); copyFolder(new File(tmpDir + officeTemplateName), new File(templatePath + officeTemplateName)); } catch (IOException ex) { String parameterFormat = "<Copy originPath='%s' targetPath='%s' deleteTarget='%s'/>"; StringBuilder sb = new StringBuilder(); sb.append("<WindowsTemplateCopyParameters>"); sb.append(String.format(parameterFormat, tmpDir + mobileServicesTemplateName, templatePath + mobileServicesTemplateName, deleteTemplates ? "true" : "false")); sb.append(String.format(parameterFormat, tmpDir + officeTemplateName, templatePath + officeTemplateName, deleteTemplates ? "true" : "false")); sb.append("</WindowsTemplateCopyParameters>"); String param = DatatypeConverter.printBase64Binary(sb.toString().getBytes("UTF-8")); String[] tmpCmd = { "cmd", "/c", tmpDir + "WindowsTemplateCopy.exe", param, }; ArrayList<String> tempenvlist = new ArrayList<String>(); for (String envval : System.getenv().keySet()) tempenvlist.add(String.format("%s=%s", envval, System.getenv().get(envval))); tempenvlist.add("PRECOMPILE_STREAMLINE_FILES=1"); String[] env = new String[tempenvlist.size()]; tempenvlist.toArray(env); Runtime rt = Runtime.getRuntime(); Process proc = rt.exec(tmpCmd, env, new File(tmpDir)); int errorCode = proc.waitFor(); //wait for elevate command to finish Thread.sleep(3000); if (!new File(templatePath + mobileServicesTemplateName).exists() || errorCode != 0) UIHelper.showException("Error copying template files. Please refer to documentation to copy manually.", new Exception()); } } else if (System.getProperty("os.name").toLowerCase().startsWith("mac")) { String[] deleteAndCopy = { "osascript", "-e", "do shell script \"rm -r \\\"/" + templatePath + mobileServicesTemplateName + "\\\"\" with administrator privileges", "-e", "do shell script \"rm -r \\\"/" + templatePath + officeTemplateName + "\\\"\" with administrator privileges", "-e", "do shell script \"cp -Rp \\\"" + tmpDir + mobileServicesTemplateName + "\\\" \\\"/" + templatePath + "\\\"\" with administrator privileges", "-e", "do shell script \"cp -Rp \\\"" + tmpDir + officeTemplateName + "\\\" \\\"/" + templatePath + "\\\"\" with administrator privileges" }; String[] copy = { "osascript", "-e", "do shell script \"cp -Rp \\\"" + tmpDir + mobileServicesTemplateName + "\\\" \\\"/" + templatePath + "\\\"\" with administrator privileges", "-e", "do shell script \"cp -Rp \\\"" + tmpDir + officeTemplateName + "\\\" \\\"/" + templatePath + "\\\"\" with administrator privileges" }; exec(deleteTemplates ? deleteAndCopy : copy, tmpDir); } else { try { if (deleteTemplates) { VirtualFile mobileTemplate = LocalFileSystem.getInstance().findFileByIoFile(new File(templatePath + mobileServicesTemplateName)); VirtualFile officeTemplate = LocalFileSystem.getInstance().findFileByIoFile(new File(templatePath + officeTemplateName)); if (mobileTemplate != null) mobileTemplate.delete(caller); if (officeTemplate != null) officeTemplate.delete(caller); } copyFolder(new File(tmpDir + mobileServicesTemplateName), new File(templatePath + mobileServicesTemplateName)); copyFolder(new File(tmpDir + officeTemplateName), new File(templatePath + officeTemplateName)); } catch (IOException ex) { JPasswordField pf = new JPasswordField(); int okCxl = JOptionPane.showConfirmDialog(null, pf, "To copy Microsoft Services templates, the plugin needs your password:", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); if (okCxl == JOptionPane.OK_OPTION) { String password = new String(pf.getPassword()); exec(new String[]{ "echo", password, "|", "sudo", "-S", "rm", "-r", tmpDir + mobileServicesTemplateName, templatePath + mobileServicesTemplateName }, tmpDir); exec(new String[]{ "echo", password, "|", "sudo", "-S", "rm", "-r", tmpDir + officeTemplateName, templatePath + officeTemplateName }, tmpDir); exec(new String[]{ "echo", password, "|", "sudo", "-S", "cp", "-Rp", tmpDir + mobileServicesTemplateName, templatePath + mobileServicesTemplateName }, tmpDir); exec(new String[]{ "echo", password, "|", "sudo", "-S", "cp", "-Rp", tmpDir + officeTemplateName, templatePath + officeTemplateName }, tmpDir); } } } } } private static void copyResourcesRecursively(File targetDir) throws IOException { InputStream fileList = ServiceCodeReferenceHelper.getTemplateResource("MobileServiceTemplate/fileList.txt"); BufferedReader in = new BufferedReader(new InputStreamReader(fileList)); String line; while ((line = in.readLine()) != null) { String[] pathParts = line.split("/"); String fileName = pathParts[pathParts.length - 1]; String path = line.replace(fileName, ""); String targetPath = targetDir.getAbsolutePath() + File.separator + "MobileServiceTemplate" + File.separator + path.replace("/", File.separator); File targetFolder = new File(targetPath); targetFolder.mkdirs(); File targetFile = new File(targetFolder, fileName); targetFile.createNewFile(); targetFile.setWritable(true); InputStream inputStream = ServiceCodeReferenceHelper.getTemplateResource("MobileServiceTemplate/" + line); byte[] content = IOUtils.readFully(inputStream, -1, true); FileOutputStream fileOutputStream = new FileOutputStream(targetFile); fileOutputStream.write(content); fileOutputStream.flush(); fileOutputStream.close(); } } private static void exec(String[] cmd, String tmpdir) throws IOException, InterruptedException { String[] env = new String[]{"PRECOMPILE_STREAMLINE_FILES=1"}; Runtime rt = Runtime.getRuntime(); Process proc = rt.exec(cmd, env, new File(tmpdir)); // any error message? StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), true); // kick them off errorGobbler.start(); proc.waitFor(); } private static String getTempLocation() { String tmpdir = System.getProperty("java.io.tmpdir"); StringBuilder sb = new StringBuilder(); sb.append(tmpdir); if (!tmpdir.endsWith(File.separator)) sb.append(File.separator); sb.append("TempAzure"); sb.append(File.separator); return sb.toString(); } private static class StreamGobbler extends Thread { InputStream is; boolean isError; public StreamGobbler(InputStream is, boolean isError) { this.is = is; this.isError = isError; } public void run() { try { InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line; StringBuilder sb = new StringBuilder(); while ((line = br.readLine()) != null) { sb.append(line).append("\n"); } is.close(); String streamContent = sb.toString(); if (isError && !streamContent.isEmpty()) UIHelper.showException("Error copying Microsoft Services templates", new AzureCmdException("Error copying Microsoft Services templates", "Error: " + streamContent)); } catch (IOException ioe) { UIHelper.showException("Error copying Microsoft Services templates", ioe); } } } public static void copyFolder(File src, File dest) throws IOException { if (src.isDirectory()) { //if directory not exists, create it if (!dest.exists()) { dest.mkdir(); } //list all the directory contents String files[] = src.list(); for (String file : files) { //construct the src and dest file structure File srcFile = new File(src, file); File destFile = new File(dest, file); //recursive copy copyFolder(srcFile, destFile); } } else { InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dest); byte[] buffer = new byte[1024]; int length; //copy the file content in bytes while ((length = in.read(buffer)) > 0) { out.write(buffer, 0, length); } in.close(); out.close(); } } }