/** * 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.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.xml.sax.SAXException; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.xpath.XPathExpressionException; import java.io.*; import java.net.URL; import java.util.Enumeration; import java.util.Scanner; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; public class ServiceCodeReferenceHelper { private static final String AZURESDK_URL = "http://zumo.blob.core.windows.net/sdk/azuresdk-android-1.1.5.zip"; private static final String TEMPLATES_URL = "/com/microsoftopentechnologies/intellij/templates/"; private static final String NOTIFICATIONHUBS_PATH = "notificationhubs/"; private static final String STRINGS_XML = "src/main/res/values/strings.xml"; @NotNull private final Project project; @NotNull private final Module module; public ServiceCodeReferenceHelper(@NotNull Project project, @NotNull Module module) { this.project = project; this.module = module; } public static InputStream getTemplateResource(String libTemplate) { return ServiceCodeReferenceHelper.class.getResourceAsStream(TEMPLATES_URL + libTemplate); } public void addNotificationHubsLibs() throws ParserConfigurationException, TransformerException, SAXException, XPathExpressionException, IOException { addReferences(NOTIFICATIONHUBS_PATH); } public void fillMobileServiceResource(String activityName, String appUrl, String appKey) throws IOException { if (module.getModuleFile() != null && module.getModuleFile().getParent() != null) { VirtualFile vf = module.getModuleFile().getParent().findFileByRelativePath(STRINGS_XML); if (vf != null) { FileDocumentManager fdm = FileDocumentManager.getInstance(); com.intellij.openapi.editor.Document document = fdm.getDocument(vf); if (document != null) { String content = document.getText(); content = content.replace(">$APPURL_" + activityName + "<", ">" + appUrl + "<"); content = content.replace(">$APPKEY_" + activityName + "<", ">" + appKey + "<"); document.setText(content); fdm.saveDocument(document); } } } } public void fillNotificationHubResource(String activityName, String senderId, String connStr, String hubName) { if (module.getModuleFile() != null && module.getModuleFile().getParent() != null) { VirtualFile vf = module.getModuleFile().getParent().findFileByRelativePath(STRINGS_XML); if (vf != null) { FileDocumentManager fdm = FileDocumentManager.getInstance(); com.intellij.openapi.editor.Document document = fdm.getDocument(vf); if (document != null) { String content = document.getText(); content = content.replace(">$SENDERID_" + activityName + "<", ">" + senderId + "<"); content = content.replace(">$CONNSTR_" + activityName + "<", ">" + connStr + "<"); content = content.replace(">$HUBNAME_" + activityName + "<", ">" + hubName + "<"); document.setText(content); fdm.saveDocument(document); } } } } public void fillOffice365Resource(String activityName, String appId, String name) { if (module.getModuleFile() != null && module.getModuleFile().getParent() != null) { VirtualFile vf = module.getModuleFile().getParent().findFileByRelativePath(STRINGS_XML); if (vf != null) { FileDocumentManager fdm = FileDocumentManager.getInstance(); com.intellij.openapi.editor.Document document = fdm.getDocument(vf); if (document != null) { String content = document.getText(); content = content.replace(">$O365_APP_ID_" + activityName + "<", ">" + appId + "<"); content = content.replace(">$O365_NAME_" + activityName + "<", ">" + name + "<"); document.setText(content); fdm.saveDocument(document); } } } } public static boolean isAndroidGradleModule(VirtualFile virtualFileDir) throws IOException { for (VirtualFile file : virtualFileDir.getChildren()) { if (file.getName().contains("build.gradle")) { if(isAndroidGradleBuildFile(file)) return true; } } return false; } public static boolean isAndroidGradleBuildFile(VirtualFile buildGradleFile) throws IOException { return getStringAndCloseStream(buildGradleFile.getInputStream()).contains("com.android.tools.build"); } private void addReferences(String zipPath) throws IOException, ParserConfigurationException, SAXException, XPathExpressionException, TransformerException { //Downloads libraries String path = System.getProperty("java.io.tmpdir"); if (!path.endsWith(File.separator)) { path = path + File.separator; } path = path + "TempAzure"; File pathFile = new File(path); if (pathFile.exists() || pathFile.mkdirs()) { path = path + File.separator + "androidAzureSDK.zip"; File zipFile = new File(path); if (!zipFile.exists()) { saveUrl(path, AZURESDK_URL); } final VirtualFile moduleFile = module.getModuleFile(); if (moduleFile != null) { moduleFile.refresh(false, false); final VirtualFile moduleDir = module.getModuleFile().getParent(); if (moduleDir != null) { moduleDir.refresh(false, false); copyJarFiles(moduleDir, zipFile, zipPath); } } } } private void copyJarFiles(VirtualFile baseDir, File zipFile, String zipPath) throws IOException { if (baseDir.isDirectory()) { final ZipFile zip = new ZipFile(zipFile); Enumeration<? extends ZipEntry> entries = zip.entries(); while (entries.hasMoreElements()) { final ZipEntry zipEntry = entries.nextElement(); if (!zipEntry.isDirectory() && zipEntry.getName().startsWith(zipPath) && zipEntry.getName().endsWith(".jar") && !(zipEntry.getName().endsWith("-sources.jar") || zipEntry.getName().endsWith("-javadoc.jar"))) { VirtualFile libsVf = null; for (VirtualFile vf : baseDir.getChildren()) { if (vf.getName().equals("libs")) { libsVf = vf; break; } } if (libsVf == null) { libsVf = baseDir.createChildDirectory(project, "libs"); } final VirtualFile libs = libsVf; ApplicationManager.getApplication().invokeAndWait(new Runnable() { @Override public void run() { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { try { InputStream mobileserviceInputStream = zip.getInputStream(zipEntry); VirtualFile msVF = libs.createChildData(project, zipEntry.getName().split("/")[1]); msVF.setBinaryContent(getArray(mobileserviceInputStream)); } catch (Throwable ex) { UIHelper.showException("Error trying to configure Azure Mobile Services", ex); } } }); } }, ModalityState.defaultModalityState()); } } } } private static void saveUrl(String filename, String urlString) throws IOException { InputStream in = null; FileOutputStream fout = null; try { in = new URL(urlString).openStream(); fout = new FileOutputStream(filename); byte data[] = new byte[1024]; int count; while ((count = in.read(data, 0, 1024)) != -1) { fout.write(data, 0, count); } } finally { if (in != null) { in.close(); } if (fout != null) { fout.close(); } } } private byte[] getArray(InputStream is) throws IOException { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int nRead; byte[] data = new byte[16384]; while ((nRead = is.read(data, 0, data.length)) != -1) { buffer.write(data, 0, nRead); } buffer.flush(); return buffer.toByteArray(); } public static String getStringAndCloseStream(InputStream is) throws IOException { //Using the trick described in this link to read whole streams in one operation: //http://stackoverflow.com/a/5445161 try { Scanner s = new Scanner(is).useDelimiter("\\A"); return s.hasNext() ? s.next() : ""; } finally { is.close(); } } @NotNull public static String getStringAndCloseStream(@NotNull InputStream is, @NotNull String charsetName) throws IOException { //Using the trick described in this link to read whole streams in one operation: //http://stackoverflow.com/a/5445161 try { Scanner s = new Scanner(is, charsetName).useDelimiter("\\A"); return s.hasNext() ? s.next() : ""; } finally { is.close(); } } }