1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.eclipse.org/org/documents/epl-v10.php 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ide.eclipse.adt.internal.project; 18 19 import com.android.ide.eclipse.adt.AndroidConstants; 20 21 import org.eclipse.core.resources.IFolder; 22 import org.eclipse.core.resources.IProject; 23 import org.eclipse.core.runtime.IPath; 24 import org.eclipse.jface.dialogs.MessageDialog; 25 import org.eclipse.swt.SWT; 26 import org.eclipse.swt.widgets.Display; 27 import org.eclipse.swt.widgets.FileDialog; 28 import org.eclipse.swt.widgets.Shell; 29 30 import java.io.File; 31 import java.io.FileInputStream; 32 import java.io.FileNotFoundException; 33 import java.io.FileOutputStream; 34 import java.io.IOException; 35 import java.util.jar.JarEntry; 36 import java.util.zip.ZipEntry; 37 import java.util.zip.ZipInputStream; 38 import java.util.zip.ZipOutputStream; 39 40 /** 41 * Export helper for project. 42 */ 43 public final class ExportHelper { 44 45 private static IExportCallback sCallback; 46 47 public interface IExportCallback { startExportWizard(IProject project)48 void startExportWizard(IProject project); 49 } 50 setCallback(IExportCallback callback)51 public static void setCallback(IExportCallback callback) { 52 sCallback = callback; 53 } 54 startExportWizard(IProject project)55 public static void startExportWizard(IProject project) { 56 if (sCallback != null) { 57 sCallback.startExportWizard(project); 58 } 59 } 60 61 /** 62 * Exports an <b>unsigned</b> version of the application created by the given project. 63 * @param project the project to export 64 */ exportProject(IProject project)65 public static void exportProject(IProject project) { 66 Shell shell = Display.getCurrent().getActiveShell(); 67 68 // get the java project to get the output directory 69 IFolder outputFolder = BaseProjectHelper.getOutputFolder(project); 70 if (outputFolder != null) { 71 IPath binLocation = outputFolder.getLocation(); 72 73 // make the full path to the package 74 String fileName = project.getName() + AndroidConstants.DOT_ANDROID_PACKAGE; 75 76 File file = new File(binLocation.toOSString() + File.separator + fileName); 77 78 if (file.exists() == false || file.isFile() == false) { 79 MessageDialog.openError(Display.getCurrent().getActiveShell(), 80 "Android IDE Plug-in", 81 String.format("Failed to export %1$s: %2$s doesn't exist!", 82 project.getName(), file.getPath())); 83 return; 84 } 85 86 // ok now pop up the file save window 87 FileDialog fileDialog = new FileDialog(shell, SWT.SAVE); 88 89 fileDialog.setText("Export Project"); 90 fileDialog.setFileName(fileName); 91 92 String saveLocation = fileDialog.open(); 93 if (saveLocation != null) { 94 // get the stream from the original file 95 96 ZipInputStream zis = null; 97 ZipOutputStream zos = null; 98 FileInputStream input = null; 99 FileOutputStream output = null; 100 101 try { 102 input = new FileInputStream(file); 103 zis = new ZipInputStream(input); 104 105 // get an output stream into the new file 106 File saveFile = new File(saveLocation); 107 output = new FileOutputStream(saveFile); 108 zos = new ZipOutputStream(output); 109 } catch (FileNotFoundException e) { 110 // only the input/output stream are throwing this exception. 111 // so we only have to close zis if output is the one that threw. 112 if (zis != null) { 113 try { 114 zis.close(); 115 } catch (IOException e1) { 116 // pass 117 } 118 } 119 120 MessageDialog.openError(shell, "Android IDE Plug-in", 121 String.format("Failed to export %1$s: %2$s doesn't exist!", 122 project.getName(), file.getPath())); 123 return; 124 } 125 126 try { 127 ZipEntry entry; 128 129 byte[] buffer = new byte[4096]; 130 131 while ((entry = zis.getNextEntry()) != null) { 132 String name = entry.getName(); 133 134 // do not take directories or anything inside the META-INF folder since 135 // we want to strip the signature. 136 if (entry.isDirectory() || name.startsWith("META-INF/")) { //$NON-NL1$ 137 continue; 138 } 139 140 ZipEntry newEntry; 141 142 // Preserve the STORED method of the input entry. 143 if (entry.getMethod() == JarEntry.STORED) { 144 newEntry = new JarEntry(entry); 145 } else { 146 // Create a new entry so that the compressed len is recomputed. 147 newEntry = new JarEntry(name); 148 } 149 150 // add the entry to the jar archive 151 zos.putNextEntry(newEntry); 152 153 // read the content of the entry from the input stream, and write it into the archive. 154 int count; 155 while ((count = zis.read(buffer)) != -1) { 156 zos.write(buffer, 0, count); 157 } 158 159 // close the entry for this file 160 zos.closeEntry(); 161 zis.closeEntry(); 162 } 163 164 } catch (IOException e) { 165 MessageDialog.openError(shell, "Android IDE Plug-in", 166 String.format("Failed to export %1$s: %2$s", 167 project.getName(), e.getMessage())); 168 } finally { 169 try { 170 zos.close(); 171 } catch (IOException e) { 172 // pass 173 } 174 try { 175 zis.close(); 176 } catch (IOException e) { 177 // pass 178 } 179 } 180 181 // this is unsigned export. Let's tell the developers to run zip align 182 MessageDialog.openWarning(shell, "Android IDE Plug-in", String.format( 183 "An unsigned package of the application was saved at\n%1$s\n\n" + 184 "Before publishing the application you will need to:\n" + 185 "- Sign the application with your release key,\n" + 186 "- run zipalign on the signed package. ZipAlign is located in <SDK>/tools/\n\n" + 187 "Aligning applications allows Android to use application resources\n" + 188 "more efficiently.", saveLocation)); 189 190 } 191 } else { 192 MessageDialog.openError(shell, "Android IDE Plug-in", 193 String.format("Failed to export %1$s: Could not get project output location", 194 project.getName())); 195 } 196 } 197 } 198