blob: 5743e165e91bee3f82db357ae288614f466324ba [file] [log] [blame]
/*
* 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);
}
}