/* * Copyright (C) 2012 The Android Open Source Project * * 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.motorola.studio.android.codesnippets; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextSelection; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.dnd.DragSourceEvent; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.wst.common.snippets.core.ISnippetItem; import org.eclipse.wst.common.snippets.core.ISnippetsEntry; import org.eclipse.wst.common.snippets.internal.ui.SnippetsView; import org.eclipse.wst.common.snippets.ui.DefaultSnippetInsertion; import com.motorola.studio.android.codesnippets.i18n.AndroidSnippetsNLS; import com.motorola.studio.android.common.log.StudioLogger; import com.motorola.studio.android.common.log.UsageDataConstants; import com.motorola.studio.android.common.utilities.EclipseUtils; import com.motorola.studio.android.manifest.AndroidProjectManifestFile; import com.motorola.studio.android.model.manifest.AndroidManifestFile; import com.motorola.studio.android.model.manifest.dom.ManifestNode; import com.motorola.studio.android.model.manifest.dom.UsesPermissionNode; public class AndroidPermissionInsertSnippet extends DefaultSnippetInsertion { @Override protected void doInsert(IEditorPart editorPart, ITextEditor textEditor, IDocument document, ITextSelection textSelection) throws BadLocationException { String replacement = getInsertString(editorPart.getEditorSite().getShell()); boolean permissionsAdded = addPermissionToManifest(editorPart, replacement); // get the Snippets View SnippetsView snippetsView = (SnippetsView) EclipseUtils.getActiveView(AndroidSnippetsStartup.SNIPPETS_VIEW_ID); // get the selected snippet ISnippetsEntry snippetEntry = snippetsView.getSelectedEntry(); if (snippetEntry != null) { String snippetLabel = snippetEntry.getLabel(); if (CodeSnippetsPlugin.getDefault() != null) { StudioLogger .collectUsageData( UsageDataConstants.WHAT_CODESNIPPET, UsageDataConstants.KIND_CODESNIPPET, "Codesnippet '" + snippetLabel + "' used. Permission added: " + permissionsAdded, //$NON-NLS-1$ AndroidSnippetsStartup.SNIPPETS_VIEW_ID, CodeSnippetsPlugin .getDefault().getBundle().getVersion().toString()); } } super.doInsert(editorPart, textEditor, document, textSelection); } /** * If the snippetText contains comment to insert uses-permission, then * it adds uses-permission to androidmanifest file * @param editorPart editor * @param snippetText text to drop */ private boolean addPermissionToManifest(IEditorPart editorPart, String snippetText) { boolean needToAddPermission = snippetText.contains("AndroidManifest.xml must have the following permission:"); //$NON-NLS-1$ boolean shouldAddToManifest = false; if (needToAddPermission) { List<String> neededPermissions = getNeededPermissions(snippetText); List<String> permissionsToBeAdded = new ArrayList<String>(neededPermissions.size()); IEditorInput input = editorPart.getEditorInput(); FileEditorInput fileEditorInput = null; ManifestNode manifestNode = null; if (input instanceof FileEditorInput) { fileEditorInput = (FileEditorInput) input; IProject project; IFile file = fileEditorInput.getFile(); project = file.getProject(); try { AndroidManifestFile androidManifestFile = AndroidProjectManifestFile.getFromProject(project); manifestNode = androidManifestFile.getManifestNode(); } catch (Exception e) { // Do nothing, just ask for the permissions. } } if (manifestNode != null) { for (String neededPermission : neededPermissions) { if (!permAlreadyExists(manifestNode, neededPermission)) { permissionsToBeAdded.add(neededPermission); } } } if (!permissionsToBeAdded.isEmpty()) { StringBuilder permMsgBuilder = new StringBuilder(); for (String neededPermission : permissionsToBeAdded) { permMsgBuilder .append(AndroidSnippetsNLS.AndroidPermissionInsertSnippet_PermissionPrefix); permMsgBuilder.append(neededPermission); permMsgBuilder .append(AndroidSnippetsNLS.AndroidPermissionInsertSnippet_PermissionSuffix); } //Ask user permission shouldAddToManifest = EclipseUtils .showQuestionDialog( AndroidSnippetsNLS.AndroidPermissionInsertSnippet_Msg_AddToManifest_Title, NLS.bind( AndroidSnippetsNLS.AndroidPermissionInsertSnippet_Msg_AddToManifest_Msg, permMsgBuilder.toString())); if (shouldAddToManifest) { AndroidManifestFile androidManifestFile = null; manifestNode = null; if (fileEditorInput != null) { addPermissionToManifest(permissionsToBeAdded, fileEditorInput, androidManifestFile, manifestNode); } } } } return shouldAddToManifest; } private List<String> getNeededPermissions(String snippetText) { //search each <uses-permission tag StringTokenizer lineToken = new StringTokenizer(snippetText, "\n\r"); //$NON-NLS-1$ List<String> neededPermissions = new ArrayList<String>(lineToken.countTokens()); while (lineToken.hasMoreTokens()) { String line = lineToken.nextToken(); if (line.contains("<uses-permission")) //$NON-NLS-1$ { String permNameToAdd = null; String androidNameStr = "android:name=\""; //$NON-NLS-1$ int beginIndex = line.indexOf(androidNameStr); int endIndex = line.indexOf("\"/>"); //$NON-NLS-1$ if ((beginIndex > 0) && (endIndex > 0)) { permNameToAdd = line.substring(beginIndex + androidNameStr.length(), endIndex); neededPermissions.add(permNameToAdd); } else { //log malformed permission statement StudioLogger .error(AndroidPermissionInsertSnippet.class, "Permission code snippet was not in the right format to enable insert of uses-permission on androidmanifest.xml" //$NON-NLS-1$ + snippetText); } } } return neededPermissions; } /** * If the snippetText contains comment to insert uses-permission, then * it asks user to add uses-permission to androidmanifest file * @param snippetText text to drop * @param input editor * @param androidManifestFile file to update * @param manifestNode node to update */ private void addPermissionToManifest(List<String> neededPermissions, IEditorInput input, AndroidManifestFile androidManifestFile, ManifestNode manifestNode) { IProject project; IFile file = ((FileEditorInput) input).getFile(); project = file.getProject(); try { androidManifestFile = AndroidProjectManifestFile.getFromProject(project); manifestNode = androidManifestFile.getManifestNode(); for (String neededPermission : neededPermissions) { if (!permAlreadyExists(manifestNode, neededPermission)) { //append permission node UsesPermissionNode usesPermissionNode = new UsesPermissionNode(neededPermission); manifestNode.addChild(usesPermissionNode); } } AndroidProjectManifestFile.saveToProject(project, androidManifestFile, true); } catch (Exception e) { StudioLogger.error(AndroidPermissionInsertSnippet.class, "Error adding snippet permissions to androidmanifest.xml.", e); //$NON-NLS-1$ } } private boolean permAlreadyExists(ManifestNode manifestNode, String neededPermission) { //Check if permissions does not exist yet boolean permAlreadyExists = false; List<UsesPermissionNode> permissionsNode = manifestNode.getUsesPermissionNodes(); if (permissionsNode != null) { for (UsesPermissionNode existentPermissionNode : permissionsNode) { String permName = existentPermissionNode.getNodeProperties() .get(UsesPermissionNode.PROP_NAME); if ((permName != null) && permName.equals(neededPermission)) { permAlreadyExists = true; break; } } } return permAlreadyExists; } @Override public void dragSetData(DragSourceEvent event, ISnippetItem item) { IEditorPart part = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() .getActiveEditor(); addPermissionToManifest(part, item.getContentString()); super.dragSetData(event, item); } }