/** * 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.components; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.Iterators; import com.google.common.collect.UnmodifiableIterator; import com.google.common.io.ByteStreams; import com.google.common.io.Files; import com.intellij.openapi.components.AbstractProjectComponent; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.*; import com.microsoftopentechnologies.intellij.helpers.ProjectFileMonitor; import com.microsoftopentechnologies.intellij.helpers.ServiceCodeReferenceHelper; import com.microsoftopentechnologies.intellij.helpers.UIHelper; import java.io.*; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class MSOpenTechToolsProject extends AbstractProjectComponent { private static final String TEMPLATES_ROOT_DIR = "build/intermediates/exploded-aar/Microsoft/templates/%s"; private static final String TEMPLATES_RESOURCE_PATH = "/com/microsoftopentechnologies/intellij/templates/MobileServiceTemplate/"; private static final String TEMPLATE_ZIP_NAME = "templates.zip"; private static final String CACHED_TEMPLATE_ZIP_NAME = "templates-%s.zip"; private VirtualFileListener virtualFileListener = null; protected MSOpenTechToolsProject(Project project) { super(project); } @Override public void projectOpened() { try { // get project root dir and check if this is an Android project if (ServiceCodeReferenceHelper.isAndroidGradleModule(myProject.getBaseDir())) { createActivityTemplates(); } else { // if a new project is being created then this method is called before // any file is created; we install a file listener to handle the template // file creation in case the project being created is an Android gradle // project virtualFileListener = new VirtualFileAdapter() { @Override public void contentsChanged(VirtualFileEvent event) { super.fileCreated(event); // if this is a build.gradle file and is an android build file then // copy the template files try { if(event.getFileName().contains("build.gradle") && ServiceCodeReferenceHelper.isAndroidGradleBuildFile(event.getFile())) { createActivityTemplates(); // now that we have the activity templates installed in this project // we don't need to listen for file changes anymore ProjectFileMonitor.getInstance().removeProjectFileListener(myProject, virtualFileListener); virtualFileListener = null; } } catch (IOException ignored) {} } }; ProjectFileMonitor.getInstance().addProjectFileListener(myProject, virtualFileListener); } } catch (IOException ignored) {} } @Override public void projectClosed() { if(virtualFileListener != null) { ProjectFileMonitor.getInstance().removeProjectFileListener(myProject, virtualFileListener); virtualFileListener = null; } } private void createActivityTemplates() throws IOException { // create the root dir to contain our templates zip if the // dir doesn't exist already File rootDir = new File(myProject.getBaseDir().getPath(), String.format( TEMPLATES_ROOT_DIR, MSOpenTechToolsApplication.getCurrent().getSettings().getPluginVersion())); rootDir.mkdirs(); // we proceed only if "templates.zip" doesn't already exist in the path File templatesZip = new File(rootDir, TEMPLATE_ZIP_NAME); if(!templatesZip.exists()) { File cachedZip = getTemplatesZip(); Files.copy(cachedZip, templatesZip); } } private File getTemplatesZip() throws IOException { // we cache the templates zip for the current version of the plugin File cachedZip = new File(System.getProperty("java.io.tmpdir"), String.format( CACHED_TEMPLATE_ZIP_NAME, MSOpenTechToolsApplication.getCurrent().getSettings().getPluginVersion())); BufferedReader reader = null; InputStream inputStream = null; ZipOutputStream outputStream = null; try { if (!cachedZip.exists()) { // read list of files to copy to zip and create the zip file outputStream = new ZipOutputStream( new BufferedOutputStream(new FileOutputStream(cachedZip))); reader = new BufferedReader( new InputStreamReader( MSOpenTechToolsProject.class.getResourceAsStream( TEMPLATES_RESOURCE_PATH + "fileList.txt"))); String line = null; while ((line = reader.readLine()) != null) { inputStream = MSOpenTechToolsProject.class.getResourceAsStream( TEMPLATES_RESOURCE_PATH + line ); ZipEntry entry = new ZipEntry(line); outputStream.putNextEntry(entry); ByteStreams.copy(inputStream, outputStream); inputStream.close(); inputStream = null; } reader.close(); reader = null; outputStream.close(); outputStream = null; } } catch (IOException e) { // if creation of the zip file fails and leaves a partially // created zip file in the file system then we delete it so // that we attempt creating it again the next time around // which we wouldn't if we discover that the file exists // already if(cachedZip.exists()) { cachedZip.delete(); } throw e; } finally { try { if (reader != null) { reader.close(); } if(inputStream != null) { inputStream.close(); } if(outputStream != null) { outputStream.close(); } } catch (IOException ignored) {} } return cachedZip; } }