From 8717ded9d3fe28e4dc342cadd29a3c391d1e5d3c Mon Sep 17 00:00:00 2001 From: zhangzhx Date: Tue, 6 Mar 2018 22:18:47 +0000 Subject: [PATCH] AWS Toolkit for Eclipse: v201803062120 Release. --- CHANGELOG.json | 3 + .../explorer/CodeCommitActionProvider.java | 7 +- .../wizard/CloneRepositoryWizard.java | 5 +- .../META-INF/MANIFEST.MF | 1 + .../eclipse/core/AwsToolkitHttpClient.java | 192 ++++++++++++++++++ .../eclipse/core/HttpClientFactory.java | 59 +++--- .../core/accounts/AccountInfoProvider.java | 12 +- .../ui/AwsToolkitErrorSupportProvider.java | 21 +- .../core/egit/jobs/CloneGitRepositoryJob.java | 5 +- .../core/exceptions/AwsActionException.java | 31 +++ .../eclipse/core/regions/RegionUtils.java | 75 ++----- .../eclipse/core/util/FileUtils.java | 56 +++++ .../amazonaws/eclipse/ec2/InstanceTypes.java | 40 ++-- .../ui/configEditor/LogTailEditorSection.java | 19 +- .../dialog/SamLocalGenerateEventDialog.java | 4 +- .../invoke/handler/InvokeFunctionHandler.java | 5 +- .../lambda/launching/SamLocalDelegate.java | 4 +- .../lambda/launching/SamLocalExecution.java | 5 +- .../NewLambdaJavaFunctionProjectWizard.java | 5 +- .../wizard/NewServerlessProjectWizard.java | 8 +- .../upload/wizard/UploadFunctionWizard.java | 5 +- .../eclipse/core/regions/RegionUtilsTest.java | 2 +- .../eclipse/core/util/FileUtilsTest.java | 58 ++++++ 23 files changed, 478 insertions(+), 144 deletions(-) create mode 100644 bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/AwsToolkitHttpClient.java create mode 100644 bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/exceptions/AwsActionException.java create mode 100644 bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/util/FileUtils.java create mode 100644 tests/com.amazonaws.eclipse.core.tests/src/com/amazonaws/eclipse/core/util/FileUtilsTest.java diff --git a/CHANGELOG.json b/CHANGELOG.json index 23a198c0..51924c6c 100644 --- a/CHANGELOG.json +++ b/CHANGELOG.json @@ -1,5 +1,8 @@ { "current": [ + "* **Update Error Report dialog to include the Github issue link.**" + ], + "v201801042359": [ "* **Merge Pull Request #93.**", "* **Resolve Issues: #87, #94, #95, #96, #97.**" ], diff --git a/bundles/com.amazonaws.eclipse.codecommit/src/com/amazonaws/eclipse/codecommit/explorer/CodeCommitActionProvider.java b/bundles/com.amazonaws.eclipse.codecommit/src/com/amazonaws/eclipse/codecommit/explorer/CodeCommitActionProvider.java index a0a30343..d6f85f23 100644 --- a/bundles/com.amazonaws.eclipse.codecommit/src/com/amazonaws/eclipse/codecommit/explorer/CodeCommitActionProvider.java +++ b/bundles/com.amazonaws.eclipse.codecommit/src/com/amazonaws/eclipse/codecommit/explorer/CodeCommitActionProvider.java @@ -53,6 +53,7 @@ import com.amazonaws.eclipse.codecommit.CodeCommitPlugin; import com.amazonaws.eclipse.codecommit.wizard.CloneRepositoryWizard; import com.amazonaws.eclipse.core.AwsToolkitCore; +import com.amazonaws.eclipse.core.exceptions.AwsActionException; import com.amazonaws.eclipse.core.mobileanalytics.AwsToolkitMetricType; import com.amazonaws.eclipse.core.regions.RegionUtils; import com.amazonaws.eclipse.core.regions.ServiceAbbreviations; @@ -117,7 +118,8 @@ protected void doRun() { } catch (Exception e) { actionFailed(); - CodeCommitPlugin.getDefault().reportException("Failed to create repository!", e); + CodeCommitPlugin.getDefault().reportException("Failed to create repository!", + new AwsActionException(AwsToolkitMetricType.EXPLORER_CODECOMMIT_CREATE_REPO.getName(), e.getMessage(), e)); } } else { actionCanceled(); @@ -254,7 +256,8 @@ protected void doRun() { dialog.open(); actionSucceeded(); } catch (Exception e) { - CodeCommitPlugin.getDefault().reportException(e.getMessage(), e); + CodeCommitPlugin.getDefault().reportException("Failed to clone CodeCommit repository!", + new AwsActionException(AwsToolkitMetricType.EXPLORER_CODECOMMIT_CLONE_REPO.getName(), e.getMessage(), e)); actionFailed(); } finally { actionFinished(); diff --git a/bundles/com.amazonaws.eclipse.codecommit/src/com/amazonaws/eclipse/codecommit/wizard/CloneRepositoryWizard.java b/bundles/com.amazonaws.eclipse.codecommit/src/com/amazonaws/eclipse/codecommit/wizard/CloneRepositoryWizard.java index 5038fc61..8fb682c5 100644 --- a/bundles/com.amazonaws.eclipse.codecommit/src/com/amazonaws/eclipse/codecommit/wizard/CloneRepositoryWizard.java +++ b/bundles/com.amazonaws.eclipse.codecommit/src/com/amazonaws/eclipse/codecommit/wizard/CloneRepositoryWizard.java @@ -41,7 +41,9 @@ import com.amazonaws.eclipse.core.egit.jobs.ImportProjectJob; import com.amazonaws.eclipse.core.egit.ui.CloneDestinationPage; import com.amazonaws.eclipse.core.egit.ui.SourceBranchPage; +import com.amazonaws.eclipse.core.exceptions.AwsActionException; import com.amazonaws.eclipse.core.maven.MavenUtils; +import com.amazonaws.eclipse.core.mobileanalytics.AwsToolkitMetricType; import com.amazonaws.eclipse.core.model.GitCredentialsDataModel; import com.amazonaws.eclipse.core.regions.RegionUtils; import com.amazonaws.eclipse.core.util.WorkbenchUtils; @@ -137,7 +139,8 @@ public void run(IProgressMonitor monitor) }); } catch (InvocationTargetException e) { CodeCommitAnalytics.trackCloneRepository(EventResult.FAILED); - CodeCommitPlugin.getDefault().reportException(e.getMessage(), e); + CodeCommitPlugin.getDefault().reportException("Failed to clone git repository.", + new AwsActionException(AwsToolkitMetricType.EXPLORER_CODECOMMIT_CLONE_REPO.getName(), e.getMessage(), e)); return false; } catch (InterruptedException e) { CodeCommitAnalytics.trackCloneRepository(EventResult.CANCELED); diff --git a/bundles/com.amazonaws.eclipse.core/META-INF/MANIFEST.MF b/bundles/com.amazonaws.eclipse.core/META-INF/MANIFEST.MF index 65af1ddc..3b5851d6 100644 --- a/bundles/com.amazonaws.eclipse.core/META-INF/MANIFEST.MF +++ b/bundles/com.amazonaws.eclipse.core/META-INF/MANIFEST.MF @@ -21,6 +21,7 @@ Export-Package: com.amazonaws.eclipse.core, com.amazonaws.eclipse.core.egit, com.amazonaws.eclipse.core.egit.jobs, com.amazonaws.eclipse.core.egit.ui, + com.amazonaws.eclipse.core.exceptions, com.amazonaws.eclipse.core.maven, com.amazonaws.eclipse.core.mobileanalytics, com.amazonaws.eclipse.core.model, diff --git a/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/AwsToolkitHttpClient.java b/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/AwsToolkitHttpClient.java new file mode 100644 index 00000000..c5aba6c9 --- /dev/null +++ b/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/AwsToolkitHttpClient.java @@ -0,0 +1,192 @@ +/* + * Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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.amazonaws.eclipse.core; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpHost; +import org.apache.http.HttpResponse; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.config.RequestConfig.Builder; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; +import org.apache.http.impl.client.HttpClientBuilder; + +public class AwsToolkitHttpClient { + private final HttpClient httpClient; + + private AwsToolkitHttpClient( + Integer connectionTimeout, + Integer socketTimeout, + String userAgent, + HttpHost proxy, + CredentialsProvider credentialsProvider) { + + Builder requestConfigBuilder = RequestConfig.custom(); + if (connectionTimeout != null) { + requestConfigBuilder.setConnectionRequestTimeout(connectionTimeout); + } + if (socketTimeout != null) { + requestConfigBuilder.setSocketTimeout(socketTimeout); + } + + HttpClientBuilder builder = HttpClientBuilder.create() + .setDefaultRequestConfig(requestConfigBuilder.build()) + .setUserAgent(userAgent); + if (proxy != null) { + builder.setProxy(proxy); + if (credentialsProvider != null) { + builder.setDefaultCredentialsProvider(credentialsProvider); + } + } + httpClient = builder + .setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)) + .build(); + } + + /** + * Head the given URL for the last modified date. + * + * @param url The target URL resource. + * @return The last modified date give the URL, or null if the date cannot be retrieved + * @throws ClientProtocolException + * @throws IOException + */ + public Date getLastModifiedDate(String url) throws ClientProtocolException, IOException { + HttpHead headMethod = new HttpHead(url); + HttpResponse response = httpClient.execute(headMethod); + Header header = response.getFirstHeader("Last-Modified"); + if (header != null) { + String lastModifiedDateString = header.getValue(); + SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz"); + try { + return dateFormat.parse(lastModifiedDateString); + } catch (ParseException e) { + return null; + } + } + return null; + } + + /** + * Fetch the content of the target URL and redirect to the output stream. + * If no content is fetched, do nothing. + * + * @param url The target URL + * @param output The OutputStream + * @throws ClientProtocolException + * @throws IOException + */ + public void outputEntityContent(String url, OutputStream output) throws ClientProtocolException, IOException { + try (InputStream inputStream = getEntityContent(url)) { + if (inputStream == null) { + return; + } + int length; + byte[] buffer = new byte[2048]; + while ((length = inputStream.read(buffer)) != -1) { + output.write(buffer, 0, length); + } + } + } + + /** + * Return the input stream of the underlying resource in the target URL. + * @param url The target URL + * @return The underlying input stream, or null if it doesn't have entity + * @throws ClientProtocolException + * @throws IOException + */ + public InputStream getEntityContent(String url) throws ClientProtocolException, IOException { + HttpGet getMethod = new HttpGet(url); + HttpResponse response = httpClient.execute(getMethod); + HttpEntity entity = response.getEntity(); + return entity == null ? null : entity.getContent(); + } + + static AwsToolkitHttpClientBuilder builder() { + return new AwsToolkitHttpClientBuilder(); + } + + static final class AwsToolkitHttpClientBuilder { + private Integer connectionTimeout; + private Integer socketTimeout; + private String userAgent; + private HttpHost proxy; + private CredentialsProvider credentialsProvider; + + private AwsToolkitHttpClientBuilder() {} + + public AwsToolkitHttpClient build() { + return new AwsToolkitHttpClient(connectionTimeout, socketTimeout, userAgent, proxy, credentialsProvider); + } + + public Integer getConnectionTimeout() { + return connectionTimeout; + } + + public AwsToolkitHttpClientBuilder setConnectionTimeout(Integer connectionTimeout) { + this.connectionTimeout = connectionTimeout; + return this; + } + + public Integer getSocketTimeout() { + return socketTimeout; + } + + public AwsToolkitHttpClientBuilder setSocketTimeout(Integer socketTimeout) { + this.socketTimeout = socketTimeout; + return this; + } + + public String getUserAgent() { + return userAgent; + } + + public AwsToolkitHttpClientBuilder setUserAgent(String userAgent) { + this.userAgent = userAgent; + return this; + } + + public HttpHost getProxy() { + return proxy; + } + + public AwsToolkitHttpClientBuilder setProxy(HttpHost proxy) { + this.proxy = proxy; + return this; + } + + public CredentialsProvider getCredentialsProvider() { + return credentialsProvider; + } + + public AwsToolkitHttpClientBuilder setCredentialsProvider(CredentialsProvider credentialsProvider) { + this.credentialsProvider = credentialsProvider; + return this; + } + } +} diff --git a/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/HttpClientFactory.java b/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/HttpClientFactory.java index 4f25e269..01e4268c 100644 --- a/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/HttpClientFactory.java +++ b/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/HttpClientFactory.java @@ -20,12 +20,7 @@ import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; import org.apache.http.auth.NTCredentials; -import org.apache.http.conn.params.ConnRoutePNames; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.params.BasicHttpParams; -import org.apache.http.params.HttpConnectionParams; -import org.apache.http.params.HttpParams; -import org.apache.http.params.HttpProtocolParams; +import org.apache.http.impl.client.BasicCredentialsProvider; import org.eclipse.core.net.proxy.IProxyData; import org.eclipse.core.net.proxy.IProxyService; import org.eclipse.core.runtime.Plugin; @@ -39,28 +34,33 @@ */ public final class HttpClientFactory { - public static DefaultHttpClient create(Plugin plugin, String url) { - HttpParams httpClientParams = new BasicHttpParams(); - + public static AwsToolkitHttpClient create(Plugin plugin, String url) { IPreferenceStore preferences = AwsToolkitCore.getDefault().getPreferenceStore(); - int connectionTimeout = preferences.getInt(PreferenceConstants.P_CONNECTION_TIMEOUT); int socketTimeout = preferences.getInt(PreferenceConstants.P_SOCKET_TIMEOUT); - HttpConnectionParams.setConnectionTimeout(httpClientParams, connectionTimeout); - HttpConnectionParams.setSoTimeout(httpClientParams, socketTimeout); - - HttpProtocolParams.setUserAgent(httpClientParams, - AwsClientUtils - .formatUserAgentString("AWS-Toolkit-For-Eclipse", plugin)); - - DefaultHttpClient httpclient = new DefaultHttpClient(httpClientParams); - configureProxy(httpclient, url); + IProxyData data = getEclipseProxyData(url); + HttpHost httpHost = null; + BasicCredentialsProvider credentialsProvider = null; + if (data != null) { + httpHost = new HttpHost(data.getHost(), data.getPort()); + if (data.isRequiresAuthentication()) { + credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(new AuthScope(httpHost), + new NTCredentials(data.getUserId(), data.getPassword(), null, null)); + } + } - return httpclient; + return AwsToolkitHttpClient.builder() + .setConnectionTimeout(connectionTimeout) + .setSocketTimeout(socketTimeout) + .setUserAgent(AwsClientUtils.formatUserAgentString("AWS-Toolkit-For-Eclipse", plugin)) + .setProxy(httpHost) + .setCredentialsProvider(credentialsProvider) + .build(); } - private static void configureProxy(DefaultHttpClient client, String url) { + private static IProxyData getEclipseProxyData(String url) { AwsToolkitCore plugin = AwsToolkitCore.getDefault(); if (plugin != null) { IProxyService proxyService = @@ -68,26 +68,17 @@ private static void configureProxy(DefaultHttpClient client, String url) { if (proxyService.isProxiesEnabled()) { try { - IProxyData[] proxyData; - proxyData = proxyService.select(new URI(url)); + IProxyData[] proxyData = proxyService.select(new URI(url)); if (proxyData.length > 0) { - - IProxyData data = proxyData[0]; - client.getParams().setParameter( - ConnRoutePNames.DEFAULT_PROXY, - new HttpHost(data.getHost(), data.getPort())); - - if (data.isRequiresAuthentication()) { - client.getCredentialsProvider().setCredentials( - new AuthScope(data.getHost(), data.getPort()), - new NTCredentials(data.getUserId(), data.getPassword(), null, null)); - } + return proxyData[0]; } } catch (URISyntaxException e) { plugin.logError(e.getMessage(), e); } } } + + return null; } private HttpClientFactory() { diff --git a/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/accounts/AccountInfoProvider.java b/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/accounts/AccountInfoProvider.java index 1f9ddc58..cd366c2e 100644 --- a/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/accounts/AccountInfoProvider.java +++ b/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/accounts/AccountInfoProvider.java @@ -15,6 +15,9 @@ package com.amazonaws.eclipse.core.accounts; import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -40,6 +43,7 @@ import com.amazonaws.eclipse.core.accounts.profiles.SdkProfilesCredentialsConfiguration; import com.amazonaws.eclipse.core.preferences.PreferenceConstants; import com.amazonaws.eclipse.core.ui.preferences.AwsAccountPreferencePage; +import com.amazonaws.eclipse.core.util.FileUtils; import com.amazonaws.util.StringUtils; /** @@ -204,19 +208,21 @@ private void reloadProfileAccountInfo(final boolean boostrapCredentialsFile, fin String credFileLocation = prefStore .getString(PreferenceConstants.P_CREDENTIAL_PROFILE_FILE_LOCATION); - File credFile = new File(credFileLocation); ProfilesConfigFile profileConfigFile = null; try { - if (!credFile.exists() && boostrapCredentialsFile) { + Path credFilePath = Paths.get(credFileLocation); + if (!Files.exists(credFilePath) && boostrapCredentialsFile) { + File credFile = FileUtils.createFileWithPermission600(credFileLocation); + // TODO We need to reconsider whether to dump an empty credentials profile when we cannot find one. ProfilesConfigFileWriter.dumpToFile( credFile, true, // overwrite=true new Profile(PreferenceConstants.DEFAULT_ACCOUNT_NAME, new BasicAWSCredentials("", ""))); } - profileConfigFile = new ProfilesConfigFile(credFile); + profileConfigFile = new ProfilesConfigFile(credFilePath.toFile()); } catch (Exception e) { String errorMsg = String.format("Failed to load credential profiles from (%s).", credFileLocation); diff --git a/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/diagnostic/ui/AwsToolkitErrorSupportProvider.java b/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/diagnostic/ui/AwsToolkitErrorSupportProvider.java index 6828d1df..9ff841b3 100644 --- a/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/diagnostic/ui/AwsToolkitErrorSupportProvider.java +++ b/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/diagnostic/ui/AwsToolkitErrorSupportProvider.java @@ -14,6 +14,8 @@ */ package com.amazonaws.eclipse.core.diagnostic.ui; +import static com.amazonaws.eclipse.core.ui.wizards.WizardWidgetFactory.newLink; + import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.Date; @@ -25,6 +27,7 @@ import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.dialogs.ErrorSupportProvider; import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jgit.lib.RepositoryBuilder; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; @@ -51,9 +54,12 @@ import com.amazonaws.eclipse.core.diagnostic.utils.AwsErrorReportUtils; import com.amazonaws.eclipse.core.diagnostic.utils.EmailMessageLauncher; import com.amazonaws.eclipse.core.diagnostic.utils.PlatformEnvironmentDataCollector; +import com.amazonaws.eclipse.core.exceptions.AwsActionException; import com.amazonaws.eclipse.core.preferences.PreferenceConstants; import com.amazonaws.eclipse.core.ui.EmailLinkListener; +import com.amazonaws.eclipse.core.ui.WebLinkListener; import com.amazonaws.eclipse.core.ui.overview.Toolkit; +import com.amazonaws.eclipse.core.ui.wizards.WizardWidgetFactory; import com.amazonaws.services.errorreport.model.ErrorDataModel; import com.amazonaws.services.errorreport.model.ErrorReportDataModel; @@ -200,6 +206,9 @@ public Control createSupportArea(Composite parent, final StatusAdapter statusAda final Text description = new Text(userInputGroup, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL); description.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + WizardWidgetFactory.newLink(userInputGroup, new WebLinkListener(), String.format( + "You can also cut a Github Issue for tracking the problem. Since it will be public, please exclude sensitive data from the report.", + "https://github.com/aws/aws-toolkit-eclipse/issues/new"), 1); /* OK button */ final Button reportBtn = new Button(parent, SWT.PUSH); @@ -210,7 +219,6 @@ public Control createSupportArea(Composite parent, final StatusAdapter statusAda @Override public void widgetSelected(SelectionEvent e) { - final String userEmail = email.getText(); final String userDescription = description.getText(); @@ -230,6 +238,10 @@ protected IStatus run(IProgressMonitor arg0) { .userDescription(userDescription) .timeOfError(sdf.format(new Date())); + if (status.getException() instanceof AwsActionException) { + errorReportDataModel.setCommandRun(((AwsActionException) status.getException()).getActionName()); + } + try { AwsErrorReportUtils.reportBugToAws(errorReportDataModel); } catch (Exception error) { @@ -262,13 +274,12 @@ public void run() { AwsToolkitCore.getDefault().logInfo("Successfully sent the error report."); return Status.OK_STATUS; - } }; job.setUser(true); job.schedule(); - + reportBtn.setEnabled(false); } }); @@ -332,6 +343,10 @@ protected Control createCustomArea(Composite parent) { EmailMessageLauncher.AWS_ECLIPSE_ERRORS_AT_AMZN, EmailMessageLauncher.AWS_ECLIPSE_ERRORS_AT_AMZN)); + WizardWidgetFactory.newLink(parent, new WebLinkListener(), String.format( + "You can also cut a Github Issue for tracking the problem. Since it will be public, please exclude sensitive data from the report.", + "https://github.com/aws/aws-toolkit-eclipse/issues/new"), 1); + EmailLinkListener emailLinkListener = new EmailLinkListener(EmailMessageLauncher.createEmptyErrorReportEmail()); link.addListener(SWT.Selection, emailLinkListener); diff --git a/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/egit/jobs/CloneGitRepositoryJob.java b/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/egit/jobs/CloneGitRepositoryJob.java index 9bc80cd5..e0a27d34 100644 --- a/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/egit/jobs/CloneGitRepositoryJob.java +++ b/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/egit/jobs/CloneGitRepositoryJob.java @@ -48,6 +48,8 @@ import com.amazonaws.eclipse.core.egit.GitRepositoryInfo.RepositoryConfigProperty; import com.amazonaws.eclipse.core.egit.ui.CloneDestinationPage; import com.amazonaws.eclipse.core.egit.ui.SourceBranchPage; +import com.amazonaws.eclipse.core.exceptions.AwsActionException; +import com.amazonaws.eclipse.core.mobileanalytics.AwsToolkitMetricType; /** * A UI sync job that manages cloning a remote Git repository to local. @@ -83,7 +85,8 @@ public void run(IProgressMonitor monitor) cloneDestinationPage.saveSettingsForClonedRepo(); } catch (Exception e) { AwsToolkitCore.getDefault() - .reportException(e.getMessage(), e); + .reportException("Failed to clone git repository.", + new AwsActionException(AwsToolkitMetricType.EXPLORER_CODECOMMIT_CLONE_REPO.getName(), e.getMessage(), e)); } } }); diff --git a/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/exceptions/AwsActionException.java b/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/exceptions/AwsActionException.java new file mode 100644 index 00000000..b1e8a931 --- /dev/null +++ b/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/exceptions/AwsActionException.java @@ -0,0 +1,31 @@ +/* + * Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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.amazonaws.eclipse.core.exceptions; + +/** + * Base exception for all AWS actions. + */ +public class AwsActionException extends RuntimeException { + private final String actionName; + + public AwsActionException(String actionName, String errorMessage, Throwable e) { + super(errorMessage, e); + this.actionName = actionName; + } + + public String getActionName() { + return actionName; + } +} diff --git a/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/regions/RegionUtils.java b/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/regions/RegionUtils.java index cc2442b0..1f17a6ab 100644 --- a/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/regions/RegionUtils.java +++ b/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/regions/RegionUtils.java @@ -20,31 +20,23 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.RandomAccessFile; import java.net.MalformedURLException; import java.net.URL; import java.util.Date; import java.util.LinkedList; import java.util.List; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpGet; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.ImageDescriptor; -import com.amazonaws.eclipse.core.AWSClientFactory; import com.amazonaws.eclipse.core.AwsToolkitCore; +import com.amazonaws.eclipse.core.AwsToolkitHttpClient; import com.amazonaws.eclipse.core.HttpClientFactory; import com.amazonaws.eclipse.core.preferences.PreferenceConstants; import com.amazonaws.regions.Regions; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.GetObjectRequest; -import com.amazonaws.services.s3.model.ObjectMetadata; /** * Utilities for loading and working with regions. The AWS regions loading priorities are: @@ -60,7 +52,6 @@ public class RegionUtils { public static final String S3_US_EAST_1_REGIONAL_ENDPOINT = "https://s3-external-1.amazonaws.com"; private static final String CLOUDFRONT_DISTRO = "http://vstoolkit.amazonwebservices.com/"; - private static final String REGIONS_METADATA_S3_BUCKET = "aws-vs-toolkit"; private static final String REGIONS_METADATA_S3_OBJECT = "ServiceEndPoints.xml"; // System property name whose value is the path of the overriding file. @@ -309,13 +300,11 @@ private static void cacheRegionsFile(File regionsFile) { } try { - AmazonS3 s3 = - AWSClientFactory.getAnonymousS3Client(); - ObjectMetadata objectMetadata = - s3.getObjectMetadata(REGIONS_METADATA_S3_BUCKET, REGIONS_METADATA_S3_OBJECT); - if (objectMetadata.getLastModified() - .after(regionsFileLastModified)) { - cacheRegionsFile(regionsFile, s3); + String url = CLOUDFRONT_DISTRO + REGIONS_METADATA_S3_OBJECT; + AwsToolkitHttpClient client = HttpClientFactory.create(AwsToolkitCore.getDefault(), url); + Date remoteFileLastModified = client.getLastModifiedDate(url); + if (remoteFileLastModified == null || remoteFileLastModified.after(regionsFileLastModified)) { + fetchFile(url, regionsFile); } } catch (Exception e) { AwsToolkitCore.getDefault().logError( @@ -415,32 +404,6 @@ private static void replaceS3GlobalEndpointWithRegional(List regions) { } } - /** - * Caches the regions file to the location given - */ - private static void cacheRegionsFile(File regionsFile, AmazonS3 s3) { - try { - truncateFile(regionsFile); - s3.getObject(new GetObjectRequest(REGIONS_METADATA_S3_BUCKET, - REGIONS_METADATA_S3_OBJECT), regionsFile); - } catch (Exception s3Exception) { - AwsToolkitCore.getDefault().logError( - "Couldn't fetch regions file from s3", s3Exception); - } - } - - /** - * Set the length of the file given to 0 bytes. - */ - private static void truncateFile(File file) - throws FileNotFoundException, IOException { - if (file.exists()) { - try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) { - raf.getChannel().truncate(0); - } - } - } - /** * Caches flag icons as necessary, also registering images for them */ @@ -478,31 +441,21 @@ private static void cacheFlags(File regionsDir) private static void fetchFile(String url, File destinationFile) throws IOException, ClientProtocolException, FileNotFoundException { - HttpClient httpclient = HttpClientFactory.create( + AwsToolkitHttpClient httpClient = HttpClientFactory.create( AwsToolkitCore.getDefault(), url); - - HttpGet httpget = new HttpGet(url); - HttpResponse response = httpclient.execute(httpget); - HttpEntity entity = response.getEntity(); - if (entity != null) { - try (InputStream instream = entity.getContent(); FileOutputStream output = new FileOutputStream(destinationFile)) { - int l; - byte[] tmp = new byte[2048]; - while ((l = instream.read(tmp)) != -1) { - output.write(tmp, 0, l); - } - } + try (FileOutputStream output = new FileOutputStream(destinationFile)) { + httpClient.outputEntityContent(url, output); } } /** - * Load regions from remote S3 bucket. + * Load regions from remote CloudFront URL. */ - public static List loadRegionsFromS3() throws IOException { - AmazonS3 s3 = AWSClientFactory.getAnonymousS3Client(); + public static List loadRegionsFromCloudFront() throws IOException { + String url = CLOUDFRONT_DISTRO + REGIONS_METADATA_S3_OBJECT; + AwsToolkitHttpClient httpClient = HttpClientFactory.create(AwsToolkitCore.getDefault(), url); try (InputStream inputStream = - s3.getObject(REGIONS_METADATA_S3_BUCKET, REGIONS_METADATA_S3_OBJECT) - .getObjectContent()) { + httpClient.getEntityContent(url)) { return parseRegionMetadata(inputStream); } } diff --git a/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/util/FileUtils.java b/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/util/FileUtils.java new file mode 100644 index 00000000..36f124c9 --- /dev/null +++ b/bundles/com.amazonaws.eclipse.core/src/com/amazonaws/eclipse/core/util/FileUtils.java @@ -0,0 +1,56 @@ +/* + * Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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.amazonaws.eclipse.core.util; + +import java.io.File; +import java.io.IOException; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.PosixFilePermission; +import java.util.HashSet; +import java.util.Set; + +public class FileUtils { + + /** + * Create a new file with permission to POSIX permission 600 or equivalent, i.e owner-only readable and writable. + * + * @param fileLocation The file location + * @return The newly created File with the permission. + * @throws IOException When fails to set POSIX permission. + * @throws FileAlreadyExistsException When the file already exists. + */ + public static File createFileWithPermission600(String fileLocation) throws IOException, FileAlreadyExistsException { + Path filePath = Paths.get(fileLocation); + if (Files.exists(filePath)) { + throw new FileAlreadyExistsException(filePath.toString()); + } + Files.createFile(filePath); + if (OsPlatformUtils.isWindows()) { + File file = filePath.toFile(); + file.setReadable(true, true); + file.setWritable(true, true); + file.setExecutable(false); + } else if (OsPlatformUtils.isLinux() || OsPlatformUtils.isMac()) { + Set perms = new HashSet<>(); + perms.add(PosixFilePermission.OWNER_READ); + perms.add(PosixFilePermission.OWNER_WRITE); + Files.setPosixFilePermissions(filePath, perms); + } + return filePath.toFile(); + } +} diff --git a/bundles/com.amazonaws.eclipse.ec2/src/com/amazonaws/eclipse/ec2/InstanceTypes.java b/bundles/com.amazonaws.eclipse.ec2/src/com/amazonaws/eclipse/ec2/InstanceTypes.java index aea7b081..6648b8e7 100644 --- a/bundles/com.amazonaws.eclipse.ec2/src/com/amazonaws/eclipse/ec2/InstanceTypes.java +++ b/bundles/com.amazonaws.eclipse.ec2/src/com/amazonaws/eclipse/ec2/InstanceTypes.java @@ -16,13 +16,16 @@ import java.io.IOException; import java.io.InputStream; -import java.net.MalformedURLException; import java.net.URL; import java.util.List; +import org.apache.http.client.ClientProtocolException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; +import com.amazonaws.eclipse.core.AwsToolkitHttpClient; +import com.amazonaws.eclipse.core.HttpClientFactory; + /** * This class describes the available EC2 instance types and the default * instance type to use in UIs. @@ -34,7 +37,7 @@ public class InstanceTypes { /** Location of the instance type description metadata */ static final String INSTANCE_TYPES_METADATA_URL = - "https://s3.amazonaws.com/aws-vs-toolkit/ServiceMeta/EC2ServiceMeta.xml"; + "http://vstoolkit.amazonwebservices.com/ServiceMeta/EC2ServiceMeta.xml"; private static boolean initialized = false; @@ -81,9 +84,9 @@ public static synchronized void initialize() { // Attempt to load the latest file from S3 try { - loadInstanceTypes(newURL(INSTANCE_TYPES_METADATA_URL)); + loadInstanceTypesFromRemote(INSTANCE_TYPES_METADATA_URL); return; - } catch (IOException e) { + } catch (Exception e) { Ec2Plugin.log(new Status(IStatus.WARNING, Ec2Plugin.PLUGIN_ID, "Unable to load Amazon EC2 instance type descriptions from Amazon S3", e)); } @@ -95,24 +98,25 @@ public static synchronized void initialize() { } } - private static URL newURL(String url) { - try { - return new URL(url); - } catch (MalformedURLException e) { - throw new RuntimeException("Unable to create URL: " + url, e); + private static void loadInstanceTypesFromRemote(String url) throws ClientProtocolException, IOException { + AwsToolkitHttpClient client = HttpClientFactory.create(Ec2Plugin.getDefault(), url); + try (InputStream inputStream = client.getEntityContent(url)) { + if (inputStream == null) { + return; + } + loadInstanceTypesFromInputStream(inputStream); } } private static void loadInstanceTypes(URL url) throws IOException { - InputStream inputStream = null; - try { - inputStream = url.openStream(); - - InstanceTypesParser parser = new InstanceTypesParser(inputStream); - instanceTypes = parser.parseInstanceTypes(); - defaultInstanceTypeId = parser.parseDefaultInstanceTypeId(); - } finally { - try {inputStream.close();} catch (Exception e) {} + try (InputStream inputStream = url.openStream()) { + loadInstanceTypesFromInputStream(inputStream); } } + + private static void loadInstanceTypesFromInputStream(InputStream inputStream) throws IOException { + InstanceTypesParser parser = new InstanceTypesParser(inputStream); + instanceTypes = parser.parseInstanceTypes(); + defaultInstanceTypeId = parser.parseDefaultInstanceTypeId(); + } } \ No newline at end of file diff --git a/bundles/com.amazonaws.eclipse.elasticbeanstalk/src/com/amazonaws/eclipse/elasticbeanstalk/server/ui/configEditor/LogTailEditorSection.java b/bundles/com.amazonaws.eclipse.elasticbeanstalk/src/com/amazonaws/eclipse/elasticbeanstalk/server/ui/configEditor/LogTailEditorSection.java index caaad00f..8d422c41 100644 --- a/bundles/com.amazonaws.eclipse.elasticbeanstalk/src/com/amazonaws/eclipse/elasticbeanstalk/server/ui/configEditor/LogTailEditorSection.java +++ b/bundles/com.amazonaws.eclipse.elasticbeanstalk/src/com/amazonaws/eclipse/elasticbeanstalk/server/ui/configEditor/LogTailEditorSection.java @@ -41,6 +41,7 @@ import com.amazonaws.AmazonServiceException; import com.amazonaws.eclipse.core.AwsToolkitCore; +import com.amazonaws.eclipse.core.AwsToolkitHttpClient; import com.amazonaws.eclipse.core.HttpClientFactory; import com.amazonaws.eclipse.elasticbeanstalk.ElasticBeanstalkPlugin; import com.amazonaws.eclipse.elasticbeanstalk.Environment; @@ -139,12 +140,7 @@ protected IStatus run(IProgressMonitor monitor) { } final List envInfos = infoResult.getEnvironmentInfo(); - DefaultHttpClient client = HttpClientFactory.create( - ElasticBeanstalkPlugin.getDefault(), - "https://s3.amazonaws.com"); - - DefaultHttpRequestRetryHandler retryhandler = new DefaultHttpRequestRetryHandler(3, true); - client.setHttpRequestRetryHandler(retryhandler); + AwsToolkitHttpClient client = HttpClientFactory.create(ElasticBeanstalkPlugin.getDefault(), "https://s3.amazonaws.com"); // For each instance, there are potentially multiple tail samples. // We just display the last one for each instance. @@ -167,13 +163,12 @@ protected IStatus run(IProgressMonitor monitor) { builder.append("Log for ").append(instanceId).append(":").append("\n\n"); EnvironmentInfoDescription envInfo = tails.get(instanceId); - - // The message is a url to fetch for logs - HttpGet rq = new HttpGet(envInfo.getMessage()); try { - HttpResponse response = client.execute(rq); - InputStream content = response.getEntity().getContent(); - builder.append(IOUtils.toString(content)); + // The message is a url to fetch for logs + InputStream content = client.getEntityContent(envInfo.getMessage()); + if (content != null) { + builder.append(IOUtils.toString(content)); + } } catch ( Exception e ) { builder.append("Exception fetching " + envInfo.getMessage()); } diff --git a/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/dialog/SamLocalGenerateEventDialog.java b/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/dialog/SamLocalGenerateEventDialog.java index fc5f178a..ed4f4c97 100644 --- a/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/dialog/SamLocalGenerateEventDialog.java +++ b/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/dialog/SamLocalGenerateEventDialog.java @@ -43,6 +43,7 @@ import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.dialogs.SaveAsDialog; +import com.amazonaws.eclipse.core.exceptions.AwsActionException; import com.amazonaws.eclipse.core.mobileanalytics.AwsToolkitMetricType; import com.amazonaws.eclipse.core.mobileanalytics.MetricsDataModel; import com.amazonaws.eclipse.core.ui.wizards.WizardWidgetFactory; @@ -188,7 +189,8 @@ private void generateEventFile() { String stdErr = stdErrOutput.toString(); if (exitValue != 0 && stdErr != null && !stdErr.isEmpty()) { - LambdaPlugin.getDefault().reportException(stdErr, null); + LambdaPlugin.getDefault().reportException("Failed to generate SAM Local event.", + new AwsActionException(AwsToolkitMetricType.SAMLOCAL_GENERATE_EVENT.getName(), stdErr, null)); AwsAction.publishFailedAction(metricsDataModel); } else { AwsAction.publishSucceededAction(metricsDataModel); diff --git a/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/invoke/handler/InvokeFunctionHandler.java b/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/invoke/handler/InvokeFunctionHandler.java index 47006faa..10da2c8e 100644 --- a/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/invoke/handler/InvokeFunctionHandler.java +++ b/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/invoke/handler/InvokeFunctionHandler.java @@ -36,6 +36,8 @@ import org.eclipse.ui.console.MessageConsoleStream; import com.amazonaws.eclipse.core.AwsToolkitCore; +import com.amazonaws.eclipse.core.exceptions.AwsActionException; +import com.amazonaws.eclipse.core.mobileanalytics.AwsToolkitMetricType; import com.amazonaws.eclipse.core.util.PluginUtils; import com.amazonaws.eclipse.lambda.LambdaAnalytics; import com.amazonaws.eclipse.lambda.LambdaPlugin; @@ -72,7 +74,8 @@ public Object execute(ExecutionEvent event) throws ExecutionException { invokeLambdaFunctionProject(selectedJavaElement); } catch (Exception e) { LambdaPlugin.getDefault().reportException( - "Failed to launch upload function wizard.", e); + "Failed to launch upload function wizard.", + new AwsActionException(AwsToolkitMetricType.LAMBDA_INVOKE_FUNCTION_DIALOG.getName(), e.getMessage(), e)); } } diff --git a/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/launching/SamLocalDelegate.java b/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/launching/SamLocalDelegate.java index 086321ee..c2c4436c 100644 --- a/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/launching/SamLocalDelegate.java +++ b/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/launching/SamLocalDelegate.java @@ -60,6 +60,7 @@ import org.eclipse.ui.console.IOConsole; import org.eclipse.ui.console.IOConsoleOutputStream; +import com.amazonaws.eclipse.core.exceptions.AwsActionException; import com.amazonaws.eclipse.core.mobileanalytics.AwsToolkitMetricType; import com.amazonaws.eclipse.core.mobileanalytics.MetricsDataModel; import com.amazonaws.eclipse.core.util.CliUtil; @@ -154,7 +155,8 @@ public void launch(ILaunchConfiguration configuration, String mode, ILaunch laun subMonitor.done(); AwsAction.publishSucceededAction(metricsDataModel); } catch (Exception e) { - LambdaPlugin.getDefault().reportException("Failed to launch SAM Local.", e); + LambdaPlugin.getDefault().reportException("Failed to launch SAM Local.", + new AwsActionException(AwsToolkitMetricType.SAMLOCAL_LAUNCH.getName(), e.getMessage(), e)); AwsAction.publishFailedAction(metricsDataModel); } } diff --git a/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/launching/SamLocalExecution.java b/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/launching/SamLocalExecution.java index 2da4fdf1..e4269ac7 100644 --- a/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/launching/SamLocalExecution.java +++ b/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/launching/SamLocalExecution.java @@ -45,6 +45,8 @@ import org.eclipse.ui.dialogs.ElementListSelectionDialog; import com.amazonaws.eclipse.core.AwsToolkitCore; +import com.amazonaws.eclipse.core.exceptions.AwsActionException; +import com.amazonaws.eclipse.core.mobileanalytics.AwsToolkitMetricType; import com.amazonaws.eclipse.lambda.LambdaPlugin; public class SamLocalExecution implements ILaunchShortcut { @@ -95,7 +97,8 @@ public static void launch(IJavaElement javaElement, LaunchMode mode) { DebugUITools.launch(configuration, mode.getMode()); } } catch (Exception e) { - LambdaPlugin.getDefault().reportException("Failed to run SAM Locol", e); + LambdaPlugin.getDefault().reportException("Failed to run SAM Locol", + new AwsActionException(AwsToolkitMetricType.SAMLOCAL_LAUNCH.getName(), e.getMessage(), e)); } } diff --git a/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/project/wizard/NewLambdaJavaFunctionProjectWizard.java b/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/project/wizard/NewLambdaJavaFunctionProjectWizard.java index 57fe6f64..1ccddc6e 100644 --- a/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/project/wizard/NewLambdaJavaFunctionProjectWizard.java +++ b/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/project/wizard/NewLambdaJavaFunctionProjectWizard.java @@ -34,7 +34,9 @@ import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.m2e.core.ui.internal.UpdateMavenProjectJob; +import com.amazonaws.eclipse.core.exceptions.AwsActionException; import com.amazonaws.eclipse.core.maven.MavenFactory; +import com.amazonaws.eclipse.core.mobileanalytics.AwsToolkitMetricType; import com.amazonaws.eclipse.core.model.MavenConfigurationDataModel; import com.amazonaws.eclipse.core.plugin.AbstractAwsPlugin; import com.amazonaws.eclipse.core.plugin.AbstractAwsProjectWizard; @@ -92,7 +94,8 @@ protected IStatus doFinish(IProgressMonitor monitor) { setDefaultJreToProjectClasspath(javaProject, monitor); } catch (Exception e) { LambdaPlugin.getDefault().reportException( - "Failed to create AWS Lambda Maven Project.", e); + "Failed to create AWS Lambda Maven Project.", + new AwsActionException(AwsToolkitMetricType.LAMBDA_NEW_LAMBDA_PROJECT_WIZARD.getName(), e.getMessage(), e)); } FunctionProjectUtil.createLambdaBlueprintProject(project, dataModel); diff --git a/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/project/wizard/NewServerlessProjectWizard.java b/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/project/wizard/NewServerlessProjectWizard.java index 451bbe26..220d1cbc 100644 --- a/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/project/wizard/NewServerlessProjectWizard.java +++ b/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/project/wizard/NewServerlessProjectWizard.java @@ -34,7 +34,9 @@ import org.eclipse.jdt.core.JavaCore; import org.eclipse.m2e.core.ui.internal.UpdateMavenProjectJob; +import com.amazonaws.eclipse.core.exceptions.AwsActionException; import com.amazonaws.eclipse.core.maven.MavenFactory; +import com.amazonaws.eclipse.core.mobileanalytics.AwsToolkitMetricType; import com.amazonaws.eclipse.core.plugin.AbstractAwsPlugin; import com.amazonaws.eclipse.core.plugin.AbstractAwsProjectWizard; import com.amazonaws.eclipse.core.util.WorkbenchUtils; @@ -100,7 +102,8 @@ protected IStatus doFinish(IProgressMonitor monitor) { setDefaultJreToProjectClasspath(javaProject, monitor); } catch (Exception e) { LambdaPlugin.getDefault().reportException( - "Failed to create AWS Serverless Maven Project.", e); + "Failed to create AWS Serverless Maven Project.", + new AwsActionException(AwsToolkitMetricType.LAMBDA_NEW_SERVERLESS_PROJECT_WIZARD.getName(), e.getMessage(), e)); } try { @@ -111,7 +114,8 @@ protected IStatus doFinish(IProgressMonitor monitor) { } catch (Exception e) { LambdaAnalytics.trackServerlessProjectCreationFailed(); - LambdaPlugin.getDefault().reportException("Failed to create new Serverless project", e); + LambdaPlugin.getDefault().reportException("Failed to create new Serverless project", + new AwsActionException(AwsToolkitMetricType.LAMBDA_NEW_SERVERLESS_PROJECT_WIZARD.getName(), e.getMessage(), e)); } LambdaAnalytics.trackServerlessProjectCreationSucceeded(); diff --git a/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/upload/wizard/UploadFunctionWizard.java b/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/upload/wizard/UploadFunctionWizard.java index 1b78cc19..41ff7d0d 100644 --- a/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/upload/wizard/UploadFunctionWizard.java +++ b/bundles/com.amazonaws.eclipse.lambda/src/com/amazonaws/eclipse/lambda/upload/wizard/UploadFunctionWizard.java @@ -26,6 +26,8 @@ import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.widgets.Display; +import com.amazonaws.eclipse.core.exceptions.AwsActionException; +import com.amazonaws.eclipse.core.mobileanalytics.AwsToolkitMetricType; import com.amazonaws.eclipse.core.plugin.AbstractAwsJobWizard; import com.amazonaws.eclipse.lambda.LambdaAnalytics; import com.amazonaws.eclipse.lambda.LambdaPlugin; @@ -109,7 +111,8 @@ protected IStatus doFinish(IProgressMonitor monitor) { UploadFunctionUtil.performFunctionUpload(dataModel, monitor, 100); } catch (Exception e) { LambdaPlugin.getDefault().reportException( - "Failed to upload project to Lambda", e); + "Failed to upload project to Lambda", + new AwsActionException(AwsToolkitMetricType.LAMBDA_UPLOAD_FUNCTION_WIZARD.getName(), e.getMessage(), e)); LambdaAnalytics.trackUploadFailed(); return Status.OK_STATUS; } diff --git a/tests/com.amazonaws.eclipse.core.tests/src/com/amazonaws/eclipse/core/regions/RegionUtilsTest.java b/tests/com.amazonaws.eclipse.core.tests/src/com/amazonaws/eclipse/core/regions/RegionUtilsTest.java index 847a99ab..8b29952e 100644 --- a/tests/com.amazonaws.eclipse.core.tests/src/com/amazonaws/eclipse/core/regions/RegionUtilsTest.java +++ b/tests/com.amazonaws.eclipse.core.tests/src/com/amazonaws/eclipse/core/regions/RegionUtilsTest.java @@ -24,7 +24,7 @@ public class RegionUtilsTest { @Test public void testRemoteRegionFile() throws IOException { - List regions = RegionUtils.loadRegionsFromS3(); + List regions = RegionUtils.loadRegionsFromCloudFront(); assertRegionEndpointsValid(regions); } diff --git a/tests/com.amazonaws.eclipse.core.tests/src/com/amazonaws/eclipse/core/util/FileUtilsTest.java b/tests/com.amazonaws.eclipse.core.tests/src/com/amazonaws/eclipse/core/util/FileUtilsTest.java new file mode 100644 index 00000000..0ea69dcb --- /dev/null +++ b/tests/com.amazonaws.eclipse.core.tests/src/com/amazonaws/eclipse/core/util/FileUtilsTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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.amazonaws.eclipse.core.util; + +import java.io.File; +import java.io.IOException; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.PosixFilePermission; +import java.util.Set; + +import org.junit.Assert; +import org.junit.Test; + +public class FileUtilsTest { + + @Test (expected = FileAlreadyExistsException.class) + public void testCreateFileWithPermission600_FileAlreadyExists() throws IOException { + Path file = Files.createTempFile("foo", "txt"); + FileUtils.createFileWithPermission600(file.toString()); + } + + public void testCreateFileWithPermission600_NewFile() throws IOException { + Path directory = Files.createTempDirectory("foo"); + Path file = Paths.get(directory.toString(), "bar"); + File newFile = FileUtils.createFileWithPermission600(file.toString()); + if (OsPlatformUtils.isLinux() || OsPlatformUtils.isMac()) { + Set permissions = Files.getPosixFilePermissions(newFile.toPath()); + Assert.assertTrue(permissions.contains(PosixFilePermission.OWNER_READ)); + Assert.assertTrue(permissions.contains(PosixFilePermission.OWNER_WRITE)); + Assert.assertFalse(permissions.contains(PosixFilePermission.OWNER_EXECUTE)); + Assert.assertFalse(permissions.contains(PosixFilePermission.GROUP_READ)); + Assert.assertFalse(permissions.contains(PosixFilePermission.GROUP_WRITE)); + Assert.assertFalse(permissions.contains(PosixFilePermission.GROUP_EXECUTE)); + Assert.assertFalse(permissions.contains(PosixFilePermission.OTHERS_READ)); + Assert.assertFalse(permissions.contains(PosixFilePermission.OTHERS_WRITE)); + Assert.assertFalse(permissions.contains(PosixFilePermission.OTHERS_EXECUTE)); + } else if (OsPlatformUtils.isWindows()) { + Assert.assertTrue(Files.isReadable(newFile.toPath())); + Assert.assertTrue(Files.isWritable(newFile.toPath())); + Assert.assertFalse(Files.isExecutable(newFile.toPath())); + } + } +}