/* * Copyright 2000-2012 JetBrains s.r.o. * * 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 org.jetbrains.android.exportSignedPackage; import com.intellij.ide.util.PropertiesComponent; import com.intellij.ide.wizard.CommitStepException; import com.intellij.openapi.compiler.CompileScope; import com.intellij.openapi.compiler.CompilerManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import org.jetbrains.android.compiler.AndroidCompileUtil; import org.jetbrains.android.compiler.artifact.ProGuardConfigFilesPanel; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.facet.AndroidFacetConfiguration; import org.jetbrains.android.util.AndroidBundle; import org.jetbrains.android.util.AndroidCommonUtils; import org.jetbrains.android.util.SaveFileListener; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.util.*; import java.util.List; /** * @author Eugene.Kudelevsky */ class ApkStep extends ExportSignedPackageWizardStep { public static final String APK_PATH_PROPERTY = "ExportedApkPath"; public static final String APK_PATH_PROPERTY_UNSIGNED = "ExportedUnsignedApkPath"; public static final String RUN_PROGUARD_PROPERTY = "AndroidRunProguardForReleaseBuild"; public static final String PROGUARD_CFG_PATHS_PROPERTY = "AndroidProguardConfigPaths"; private TextFieldWithBrowseButton myApkPathField; private JPanel myContentPanel; private JLabel myApkPathLabel; private JCheckBox myProguardCheckBox; private ProGuardConfigFilesPanel myProGuardConfigFilesPanel; private final ExportSignedPackageWizard myWizard; private boolean myInited; @Nullable private static String getContentRootPath(Module module) { VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots(); if (contentRoots.length != 0) { VirtualFile contentRoot = contentRoots[0]; if (contentRoot != null) return contentRoot.getPath(); } return null; } public ApkStep(ExportSignedPackageWizard wizard) { myWizard = wizard; myApkPathLabel.setLabelFor(myApkPathField); myApkPathField.getButton().addActionListener( new SaveFileListener(myContentPanel, myApkPathField, AndroidBundle.message("android.extract.package.choose.dest.apk"), "apk") { @Override protected String getDefaultLocation() { Module module = myWizard.getFacet().getModule(); return getContentRootPath(module); } }); myProguardCheckBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { myProGuardConfigFilesPanel.setEnabled(myProguardCheckBox.isSelected()); } }); myContentPanel.setPreferredSize(new Dimension(myContentPanel.getPreferredSize().width, 250)); } @Override public void _init() { if (myInited) return; final AndroidFacet facet = myWizard.getFacet(); Module module = facet.getModule(); PropertiesComponent properties = PropertiesComponent.getInstance(module.getProject()); String lastModule = properties.getValue(ChooseModuleStep.MODULE_PROPERTY); String lastApkPath = properties.getValue(getApkPathPropertyName()); if (lastApkPath != null && module.getName().equals(lastModule)) { myApkPathField.setText(FileUtil.toSystemDependentName(lastApkPath)); } else { String contentRootPath = getContentRootPath(module); if (contentRootPath != null) { String defaultPath = FileUtil.toSystemDependentName(contentRootPath + "/" + module.getName() + ".apk"); myApkPathField.setText(defaultPath); } } final String runProguardPropValue = properties.getValue(RUN_PROGUARD_PROPERTY); boolean selected; if (runProguardPropValue != null) { selected = Boolean.parseBoolean(runProguardPropValue); } else { selected = facet.getProperties().RUN_PROGUARD; } myProguardCheckBox.setSelected(selected); myProGuardConfigFilesPanel.setEnabled(selected); final String proguardCfgPathsStr = properties.getValue(PROGUARD_CFG_PATHS_PROPERTY); final String[] proguardCfgPaths = proguardCfgPathsStr != null ? parseAndCheckProguardCfgPaths(proguardCfgPathsStr) : null; if (proguardCfgPaths != null && proguardCfgPaths.length > 0) { myProGuardConfigFilesPanel.setOsPaths(Arrays.asList(proguardCfgPaths)); } else { final AndroidFacetConfiguration configuration = facet.getConfiguration(); if (configuration.getState().RUN_PROGUARD) { myProGuardConfigFilesPanel.setUrls(facet.getProperties().myProGuardCfgFiles); } else { final List<String> urls = new ArrayList<String>(); urls.add(AndroidCommonUtils.PROGUARD_SYSTEM_CFG_FILE_URL); final Pair<VirtualFile, Boolean> pair = AndroidCompileUtil.getDefaultProguardConfigFile(facet); if (pair != null) { urls.add(pair.getFirst().getUrl()); } myProGuardConfigFilesPanel.setUrls(urls); } } myInited = true; } @NotNull private static String[] parseAndCheckProguardCfgPaths(@NotNull String pathsStr) { if (pathsStr.length() == 0) { return ArrayUtil.EMPTY_STRING_ARRAY; } final String[] paths = pathsStr.split(File.pathSeparator); if (paths.length == 0) { return ArrayUtil.EMPTY_STRING_ARRAY; } for (String path : paths) { if (LocalFileSystem.getInstance().refreshAndFindFileByPath(path) == null) { return ArrayUtil.EMPTY_STRING_ARRAY; } } return paths; } @NotNull private static String mergeProguardCfgPathsToOneString(@NotNull Collection<String> paths) { final StringBuilder builder = new StringBuilder(); for (Iterator<String> it = paths.iterator(); it.hasNext(); ) { builder.append(it.next()); if (it.hasNext()) { builder.append(File.pathSeparator); } } return builder.toString(); } private String getApkPathPropertyName() { return myWizard.isSigned() ? APK_PATH_PROPERTY : APK_PATH_PROPERTY_UNSIGNED; } @Override public JComponent getComponent() { return myContentPanel; } @Override protected boolean canFinish() { return true; } @Override public String getHelpId() { return "reference.android.reference.extract.signed.package.specify.apk.location"; } @Override public void _commit(boolean finishChosen) throws CommitStepException { final String apkPath = myApkPathField.getText().trim(); if (apkPath.length() == 0) { throw new CommitStepException(AndroidBundle.message("android.extract.package.specify.apk.path.error")); } AndroidFacet facet = myWizard.getFacet(); PropertiesComponent properties = PropertiesComponent.getInstance(myWizard.getProject()); properties.setValue(ChooseModuleStep.MODULE_PROPERTY, facet != null ? facet.getModule().getName() : ""); properties.setValue(getApkPathPropertyName(), apkPath); File folder = new File(apkPath).getParentFile(); if (folder == null) { throw new CommitStepException(AndroidBundle.message("android.cannot.create.file.error", apkPath)); } try { if (!folder.exists()) { folder.mkdirs(); } } catch (Exception e) { throw new CommitStepException(e.getMessage()); } final CompileScope compileScope = CompilerManager.getInstance(myWizard.getProject()). createModuleCompileScope(facet.getModule(), true); AndroidCompileUtil.setReleaseBuild(compileScope); properties.setValue(RUN_PROGUARD_PROPERTY, Boolean.toString(myProguardCheckBox.isSelected())); if (myProguardCheckBox.isSelected()) { final List<String> proguardOsCfgPaths = myProGuardConfigFilesPanel.getOsPaths(); if (proguardOsCfgPaths.isEmpty()) { throw new CommitStepException(AndroidBundle.message("android.extract.package.specify.proguard.cfg.path.error")); } final String proguardPathsStr = mergeProguardCfgPathsToOneString(proguardOsCfgPaths); properties.setValue(PROGUARD_CFG_PATHS_PROPERTY, proguardPathsStr); for (String path : proguardOsCfgPaths) { if (!new File(path).isFile()) { throw new CommitStepException("Cannot find file " + path); } } compileScope.putUserData(AndroidCompileUtil.PROGUARD_CFG_PATHS_KEY, proguardPathsStr); } myWizard.setCompileScope(compileScope); myWizard.setApkPath(apkPath); } @Override protected void commitForNext() throws CommitStepException { } private void createUIComponents() { myProGuardConfigFilesPanel = new ProGuardConfigFilesPanel() { @Nullable @Override protected AndroidFacet getFacet() { return myWizard.getFacet(); } }; } }