Java tutorial
/** * Copyright (c) Microsoft Corporation * <p/> * All rights reserved. * <p/> * MIT License * <p/> * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated * documentation files (the "Software"), to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and * to permit persons to whom the Software is furnished to do so, subject to the following conditions: * <p/> * The above copyright notice and this permission notice shall be included in all copies or substantial portions of * the Software. * <p/> * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.microsoft.tooling.msservices.helpers.azure; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayInputStream; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Writer; import java.lang.reflect.Type; import java.net.URI; import java.net.URISyntaxException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.Semaphore; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPReply; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import com.google.common.base.Optional; import com.google.common.io.CharStreams; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonSyntaxException; import com.google.gson.reflect.TypeToken; import com.microsoft.azure.management.resources.ResourceManagementClient; import com.microsoft.azure.management.resources.models.ResourceGroupExtended; import com.microsoft.azure.management.websites.WebSiteManagementClient; import com.microsoft.azure.management.websites.models.WebHostingPlan; import com.microsoft.tooling.msservices.components.AppSettingsNames; import com.microsoft.tooling.msservices.components.DefaultLoader; import com.microsoft.tooling.msservices.components.PluginSettings; import com.microsoft.tooling.msservices.helpers.IDEHelper.ArtifactDescriptor; import com.microsoft.tooling.msservices.helpers.IDEHelper.ProjectDescriptor; import com.microsoft.tooling.msservices.helpers.NotNull; import com.microsoft.tooling.msservices.helpers.Nullable; import com.microsoft.tooling.msservices.helpers.OpenSSLHelper; import com.microsoft.tooling.msservices.helpers.StringHelper; import com.microsoft.tooling.msservices.helpers.XmlHelper; import com.microsoft.tooling.msservices.helpers.auth.AADManager; import com.microsoft.tooling.msservices.helpers.auth.AADManagerImpl; import com.microsoft.tooling.msservices.helpers.auth.UserInfo; import com.microsoft.tooling.msservices.helpers.azure.rest.AzureAADHelper; import com.microsoft.tooling.msservices.helpers.azure.rest.AzureCertificateHelper; import com.microsoft.tooling.msservices.helpers.azure.rest.MobileServiceRestManager; import com.microsoft.tooling.msservices.helpers.azure.rest.RestServiceManager.ContentType; import com.microsoft.tooling.msservices.helpers.azure.rest.RestServiceManagerBaseImpl; import com.microsoft.tooling.msservices.helpers.azure.rest.model.CustomAPIData; import com.microsoft.tooling.msservices.helpers.azure.rest.model.JobData; import com.microsoft.tooling.msservices.helpers.azure.rest.model.LogData; import com.microsoft.tooling.msservices.helpers.azure.rest.model.MobileServiceData; import com.microsoft.tooling.msservices.helpers.azure.rest.model.TableColumnData; import com.microsoft.tooling.msservices.helpers.azure.rest.model.TableData; import com.microsoft.tooling.msservices.helpers.azure.rest.model.TablePermissionsData; import com.microsoft.tooling.msservices.helpers.azure.rest.model.TableScriptData; import com.microsoft.tooling.msservices.helpers.azure.sdk.AzureSDKHelper; import com.microsoft.tooling.msservices.helpers.azure.sdk.SDKRequestCallback; import com.microsoft.tooling.msservices.helpers.tasks.CancellableTask; import com.microsoft.tooling.msservices.model.Subscription; import com.microsoft.tooling.msservices.model.ms.Column; import com.microsoft.tooling.msservices.model.ms.CustomAPI; import com.microsoft.tooling.msservices.model.ms.CustomAPIPermissions; import com.microsoft.tooling.msservices.model.ms.Job; import com.microsoft.tooling.msservices.model.ms.LogEntry; import com.microsoft.tooling.msservices.model.ms.MobileService; import com.microsoft.tooling.msservices.model.ms.PermissionItem; import com.microsoft.tooling.msservices.model.ms.Script; import com.microsoft.tooling.msservices.model.ms.SqlDb; import com.microsoft.tooling.msservices.model.ms.SqlServer; import com.microsoft.tooling.msservices.model.ms.Table; import com.microsoft.tooling.msservices.model.ms.TablePermissions; import com.microsoft.tooling.msservices.model.storage.StorageAccount; import com.microsoft.tooling.msservices.model.vm.AffinityGroup; import com.microsoft.tooling.msservices.model.vm.CloudService; import com.microsoft.tooling.msservices.model.vm.Location; import com.microsoft.tooling.msservices.model.vm.VirtualMachine; import com.microsoft.tooling.msservices.model.vm.VirtualMachineImage; import com.microsoft.tooling.msservices.model.vm.VirtualMachineSize; import com.microsoft.tooling.msservices.model.vm.VirtualNetwork; import com.microsoft.tooling.msservices.model.ws.WebHostingPlanCache; import com.microsoft.tooling.msservices.model.ws.WebSite; import com.microsoft.tooling.msservices.model.ws.WebSiteConfiguration; import com.microsoft.tooling.msservices.model.ws.WebSitePublishSettings; import com.microsoft.tooling.msservices.model.ws.WebSitePublishSettings.FTPPublishProfile; import com.microsoft.tooling.msservices.model.ws.WebSitePublishSettings.PublishProfile; import com.microsoft.tooling.msservices.serviceexplorer.EventHelper.EventWaitHandle; import com.microsoft.windowsazure.Configuration; import com.microsoft.windowsazure.core.OperationStatusResponse; import com.microsoft.windowsazure.management.ManagementClient; import com.microsoft.windowsazure.management.compute.ComputeManagementClient; import com.microsoft.windowsazure.management.compute.models.DeploymentCreateParameters; import com.microsoft.windowsazure.management.compute.models.DeploymentGetResponse; import com.microsoft.windowsazure.management.compute.models.DeploymentSlot; import com.microsoft.windowsazure.management.compute.models.ServiceCertificateListResponse; import com.microsoft.windowsazure.management.models.SubscriptionGetResponse; import com.microsoft.windowsazure.management.network.NetworkManagementClient; import com.microsoft.windowsazure.management.storage.StorageManagementClient; import com.microsoftopentechnologies.azuremanagementutil.rest.SubscriptionTransformer; import com.microsoftopentechnologies.azuremanagementutil.rest.WindowsAzureRestUtils; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; public class AzureManagerImpl implements AzureManager { private interface AzureSDKClientProvider<V extends Closeable> { @NotNull V getSSLClient(@NotNull Subscription subscription) throws Throwable; @NotNull V getAADClient(@NotNull String subscriptionId, @NotNull String accessToken) throws Throwable; } private static class EventWaitHandleImpl implements EventWaitHandle { Semaphore eventSignal = new Semaphore(0, true); @Override public void waitEvent(@NotNull Runnable callback) throws AzureCmdException { try { eventSignal.acquire(); callback.run(); } catch (InterruptedException e) { throw new AzureCmdException("Unable to aquire permit", e); } } private synchronized void signalEvent() { if (eventSignal.availablePermits() == 0) { eventSignal.release(); } } } private static AzureManager instance; private static Gson gson; private AADManager aadManager; private ReentrantReadWriteLock authDataLock = new ReentrantReadWriteLock(false); private Map<String, Subscription> subscriptions; private UserInfo userInfo; private ReentrantReadWriteLock subscriptionMapLock = new ReentrantReadWriteLock(false); private Map<String, ReentrantReadWriteLock> lockBySubscriptionId = new HashMap<String, ReentrantReadWriteLock>(); private Map<String, UserInfo> userInfoBySubscriptionId; private Map<String, SSLSocketFactory> sslSocketFactoryBySubscriptionId; private String accessToken; // this field to be used from cspack ant task only private ReentrantReadWriteLock userMapLock = new ReentrantReadWriteLock(false); private Map<UserInfo, ReentrantReadWriteLock> lockByUser; private Map<UserInfo, String> accessTokenByUser; private ReentrantReadWriteLock subscriptionsChangedLock = new ReentrantReadWriteLock(true); private Set<EventWaitHandleImpl> subscriptionsChangedHandles; private AzureManagerImpl() { authDataLock.writeLock().lock(); try { aadManager = AADManagerImpl.getManager(); loadSubscriptions(); loadUserInfo(); loadSSLSocketFactory(); // todo???? removeInvalidUserInfo(); removeUnusedSubscriptions(); storeSubscriptions(); storeUserInfo(); accessTokenByUser = new HashMap<UserInfo, String>(); lockByUser = new HashMap<UserInfo, ReentrantReadWriteLock>(); subscriptionsChangedHandles = new HashSet<EventWaitHandleImpl>(); } finally { authDataLock.writeLock().unlock(); } } private AzureManagerImpl(String accessToken) { authDataLock.writeLock().lock(); try { // aadManager = AADManagerImpl.getManager(); this.accessToken = accessToken; // loadSubscriptions(); // loadUserInfo(); // loadSSLSocketFactory(); // todo???? // // removeInvalidUserInfo(); // removeUnusedSubscriptions(); // // storeSubscriptions(); // storeUserInfo(); // // accessTokenByUser = new HashMap<UserInfo, String>(); // lockByUser = new HashMap<UserInfo, ReentrantReadWriteLock>(); // subscriptionsChangedHandles = new HashSet<EventWaitHandleImpl>(); } finally { authDataLock.writeLock().unlock(); } } /** * This method for now is supposed to be used from cspack ant task only */ public static synchronized AzureManager initManager(String accessToken) { instance = new AzureManagerImpl(accessToken); return instance; } @NotNull public static synchronized AzureManager getManager() { if (instance == null) { gson = new GsonBuilder().enableComplexMapKeySerialization().create(); instance = new AzureManagerImpl(); } return instance; } @Override public void authenticate() throws AzureCmdException { final PluginSettings settings = DefaultLoader.getPluginComponent().getSettings(); final String managementUri = settings.getAzureServiceManagementUri(); final UserInfo userInfo = aadManager.authenticate(managementUri, "Sign in to your Azure account"); setUserInfo(userInfo); List<Subscription> subscriptions = requestWithToken(userInfo, new RequestCallback<List<Subscription>>() { @Override public List<Subscription> execute() throws Throwable { String accessToken = getAccessToken(userInfo); String subscriptionsXML = AzureAADHelper.executeRequest(managementUri, "subscriptions", ContentType.Json, "GET", null, accessToken, new RestServiceManagerBaseImpl() { @NotNull @Override public String executePollRequest(@NotNull String managementUrl, @NotNull String path, @NotNull ContentType contentType, @NotNull String method, @Nullable String postData, @NotNull String pollPath, @NotNull HttpsURLConnectionProvider sslConnectionProvider) throws AzureCmdException { throw new UnsupportedOperationException(); } }); return parseSubscriptionsXML(subscriptionsXML); } }); for (Subscription subscription : subscriptions) { UserInfo subscriptionUser = new UserInfo(subscription.getTenantId(), userInfo.getUniqueName()); aadManager.authenticate(subscriptionUser, managementUri, "Sign in to your Azure account"); updateSubscription(subscription, subscriptionUser); } } @Override public boolean authenticated() { return getUserInfo() != null; } @Override public boolean authenticated(@NotNull String subscriptionId) { return !hasSSLSocketFactory(subscriptionId) && hasUserInfo(subscriptionId); } @Override public void clearAuthentication() { setUserInfo(null); } @Override public void importPublishSettingsFile(@NotNull String publishSettingsFilePath) throws AzureCmdException { List<Subscription> subscriptions = importSubscription(publishSettingsFilePath); for (Subscription subscription : subscriptions) { try { SSLSocketFactory sslSocketFactory = initSSLSocketFactory(subscription.getManagementCertificate()); updateSubscription(subscription, sslSocketFactory); } catch (Exception ex) { throw new AzureCmdException("Error importing publish settings", ex); } } } @Override public boolean usingCertificate() { authDataLock.readLock().lock(); try { return sslSocketFactoryBySubscriptionId.size() > 0; } finally { authDataLock.readLock().unlock(); } } @Override public boolean usingCertificate(@NotNull String subscriptionId) { return hasSSLSocketFactory(subscriptionId); } @Override public void clearImportedPublishSettingsFiles() { authDataLock.writeLock().lock(); try { sslSocketFactoryBySubscriptionId.clear(); removeUnusedSubscriptions(); storeSubscriptions(); } finally { authDataLock.writeLock().unlock(); } } @NotNull @Override public List<Subscription> getFullSubscriptionList() throws AzureCmdException { authDataLock.readLock().lock(); try { List<Subscription> result = new ArrayList<Subscription>(); for (Subscription subscription : subscriptions.values()) { result.add(subscription); } return result; } finally { authDataLock.readLock().unlock(); } } @NotNull @Override public List<Subscription> getSubscriptionList() throws AzureCmdException { authDataLock.readLock().lock(); try { List<Subscription> result = new ArrayList<Subscription>(); for (Subscription subscription : subscriptions.values()) { if (subscription.isSelected()) { result.add(subscription); } } return result; } finally { authDataLock.readLock().unlock(); } } @Override public void setSelectedSubscriptions(@NotNull List<String> selectedList) throws AzureCmdException { authDataLock.writeLock().lock(); try { for (String subscriptionId : subscriptions.keySet()) { Subscription subscription = subscriptions.get(subscriptionId); subscription.setSelected(selectedList.contains(subscriptionId)); } storeSubscriptions(); } finally { authDataLock.writeLock().unlock(); } notifySubscriptionsChanged(); } @NotNull @Override public EventWaitHandle registerSubscriptionsChanged() throws AzureCmdException { subscriptionsChangedLock.writeLock().lock(); try { EventWaitHandleImpl handle = new EventWaitHandleImpl(); subscriptionsChangedHandles.add(handle); return handle; } finally { subscriptionsChangedLock.writeLock().unlock(); } } @Override public void unregisterSubscriptionsChanged(@NotNull EventWaitHandle handle) throws AzureCmdException { if (!(handle instanceof EventWaitHandleImpl)) { throw new AzureCmdException("Invalid handle instance"); } subscriptionsChangedLock.writeLock().lock(); try { subscriptionsChangedHandles.remove(handle); } finally { subscriptionsChangedLock.writeLock().unlock(); } ((EventWaitHandleImpl) handle).signalEvent(); } @NotNull @Override public List<SqlDb> getSqlDb(@NotNull String subscriptionId, @NotNull SqlServer server) throws AzureCmdException { try { String path = String.format("/%s/services/sqlservers/servers/%s/databases?contentview=generic", subscriptionId, server.getName()); String xml = executeGetRequest(subscriptionId, path); List<SqlDb> res = new ArrayList<SqlDb>(); NodeList nl = (NodeList) XmlHelper.getXMLValue(xml, "//ServiceResource", XPathConstants.NODESET); for (int i = 0; i != nl.getLength(); i++) { SqlDb sqls = new SqlDb(); sqls.setName(XmlHelper.getChildNodeValue(nl.item(i), "Name")); sqls.setEdition(XmlHelper.getChildNodeValue(nl.item(i), "Edition")); sqls.setServer(server); res.add(sqls); } return res; } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error getting database list", t); } } @NotNull @Override public List<SqlServer> getSqlServers(@NotNull String subscriptionId) throws AzureCmdException { try { String path = String.format("/%s/services/sqlservers/servers", subscriptionId); String xml = executeGetRequest(subscriptionId, path); List<SqlServer> res = new ArrayList<SqlServer>(); NodeList nl = (NodeList) XmlHelper.getXMLValue(xml, "//Server", XPathConstants.NODESET); for (int i = 0; i != nl.getLength(); i++) { SqlServer sqls = new SqlServer(); sqls.setAdmin(XmlHelper.getChildNodeValue(nl.item(i), "AdministratorLogin")); sqls.setName(XmlHelper.getChildNodeValue(nl.item(i), "Name")); sqls.setRegion(XmlHelper.getChildNodeValue(nl.item(i), "Location")); res.add(sqls); } return res; } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error getting server list", t); } } @NotNull @Override public List<MobileService> getMobileServiceList(@NotNull String subscriptionId) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices", subscriptionId); String json = executeGetRequest(subscriptionId, path); Type type = new TypeToken<ArrayList<MobileServiceData>>() { }.getType(); List<MobileServiceData> tempRes = new Gson().fromJson(json, type); List<MobileService> res = new ArrayList<MobileService>(); for (MobileServiceData item : tempRes) { MobileService ser = new MobileService(); ser.setName(item.getName()); ser.setType(item.getType()); ser.setState(item.getState()); ser.setSelfLink(item.getSelflink()); ser.setAppUrl(item.getApplicationUrl()); ser.setAppKey(item.getApplicationKey()); ser.setMasterKey(item.getMasterKey()); ser.setWebspace(item.getWebspace()); ser.setRegion(item.getRegion()); ser.setMgmtPortalLink(item.getManagementPortalLink()); ser.setSubcriptionId(subscriptionId); if (item.getPlatform() != null && item.getPlatform().equals("dotNet")) { ser.setRuntime(MobileService.NET_RUNTIME); } else { ser.setRuntime(MobileService.NODE_RUNTIME); } for (MobileServiceData.Table table : item.getTables()) { Table t = new Table(); t.setName(table.getName()); t.setSelfLink(table.getSelflink()); ser.getTables().add(t); } res.add(ser); } return res; } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error getting service list", t); } } @Override public void createMobileService(@NotNull String subscriptionId, @NotNull String region, @NotNull String username, @NotNull String password, @NotNull String mobileServiceName, @Nullable String server, @Nullable String database) throws AzureCmdException { try { String path = String.format("/%s/applications", subscriptionId); String JSONParameter; if (database == null || server == null) { String zumoServerId = UUID.randomUUID().toString().replace("-", ""); String zumoDBId = UUID.randomUUID().toString().replace("-", ""); String dbName = mobileServiceName + "_db"; JSONParameter = "{'SchemaVersion':'2012-05.1.0','Location':'" + region + "','ExternalResources':{},'InternalResources':{'ZumoMobileService':" + "{'ProvisioningParameters':{'Name':'" + mobileServiceName + "','Location':'" + region + "'},'ProvisioningConfigParameters':{'Server':{'StringConcat':" + "[{'ResourceReference':'ZumoSqlServer_" + zumoServerId + ".Name'},'.database.windows.net']},'Database':{'ResourceReference':'ZumoSqlDatabase_" + zumoDBId + ".Name'},'AdministratorLogin':'" + username + "','AdministratorLoginPassword':'" + password + "'},'Version':'2012-05-21.1.0'," + "'Name':'ZumoMobileService','Type':'Microsoft.WindowsAzure.MobileServices.MobileService'},'ZumoSqlServer_" + zumoServerId + "':{'ProvisioningParameters':{'AdministratorLogin':'" + username + "','AdministratorLoginPassword':'" + password + "','Location':'" + region + "'},'ProvisioningConfigParameters':{'FirewallRules':[{'Name':'AllowAllWindowsAzureIps','StartIPAddress':'0.0.0.0','EndIPAddress':'0.0.0.0'}]}," + "'Version':'1.0','Name':'ZumoSqlServer_" + zumoServerId + "','Type':'Microsoft.WindowsAzure.SQLAzure.Server'},'ZumoSqlDatabase_" + zumoDBId + "':{'ProvisioningParameters':{'Name':'" + dbName + "','Edition':'WEB','MaxSizeInGB':'1','DBServer':{'ResourceReference':'ZumoSqlServer_" + zumoServerId + ".Name'},'CollationName':'SQL_Latin1_General_CP1_CI_AS'},'Version':'1.0','Name':'ZumoSqlDatabase_" + zumoDBId + "','Type':'Microsoft.WindowsAzure.SQLAzure.DataBase'}}}"; } else { String zumoServerId = UUID.randomUUID().toString().replace("-", ""); String zumoDBId = UUID.randomUUID().toString().replace("-", ""); JSONParameter = "{'SchemaVersion':'2012-05.1.0','Location':'West US','ExternalResources':{'ZumoSqlServer_" + zumoServerId + "':{'Name':'ZumoSqlServer_" + zumoServerId + "'," + "'Type':'Microsoft.WindowsAzure.SQLAzure.Server','URI':'https://management.core.windows.net:8443/" + subscriptionId + "/services/sqlservers/servers/" + server + "'}," + "'ZumoSqlDatabase_" + zumoDBId + "':{'Name':'ZumoSqlDatabase_" + zumoDBId + "','Type':'Microsoft.WindowsAzure.SQLAzure.DataBase'," + "'URI':'https://management.core.windows.net:8443/" + subscriptionId + "/services/sqlservers/servers/" + server + "/databases/" + database + "'}}," + "'InternalResources':{'ZumoMobileService':{'ProvisioningParameters'" + ":{'Name':'" + mobileServiceName + "','Location':'" + region + "'},'ProvisioningConfigParameters':{'Server':{'StringConcat':[{'ResourceReference':'ZumoSqlServer_" + zumoServerId + ".Name'}," + "'.database.windows.net']},'Database':{'ResourceReference':'ZumoSqlDatabase_" + zumoDBId + ".Name'},'AdministratorLogin':" + "'" + username + "','AdministratorLoginPassword':'" + password + "'},'Version':'2012-05-21.1.0','Name':'ZumoMobileService','Type':" + "'Microsoft.WindowsAzure.MobileServices.MobileService'}}}"; } String xmlParameter = String.format( "<?xml version=\"1.0\" encoding=\"utf-8\"?><Application xmlns=\"http://schemas.microsoft.com/windowsazure\"><Name>%s</Name>" + "<Label>%s</Label><Description>%s</Description><Configuration>%s</Configuration></Application>", mobileServiceName + "mobileservice", mobileServiceName, mobileServiceName, new BASE64Encoder().encode(JSONParameter.getBytes())); executePollRequest(subscriptionId, path, ContentType.Xml, "POST", xmlParameter, String.format("/%s/operations/", subscriptionId)); String xml = executeGetRequest(subscriptionId, String.format("/%s/applications/%s", subscriptionId, mobileServiceName + "mobileservice")); NodeList statusNode = ((NodeList) XmlHelper.getXMLValue(xml, "//Application/State", XPathConstants.NODESET)); if (!(statusNode.getLength() > 0 && statusNode.item(0).getTextContent().equals("Healthy"))) { deleteMobileService(subscriptionId, mobileServiceName); String errors = ((String) XmlHelper.getXMLValue(xml, "//FailureCode[text()]", XPathConstants.STRING)); String errorMessage = ((String) XmlHelper.getXMLValue(errors, "//Message[text()]", XPathConstants.STRING)); throw new AzureCmdException("Error creating service", errorMessage); } } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error creating service", t); } } @Override public void deleteMobileService(@NotNull String subscriptionId, @NotNull String mobileServiceName) { String mspath = String.format("/%s/services/mobileservices/mobileservices/%s?deletedata=true", subscriptionId, mobileServiceName); try { executePollRequest(subscriptionId, mspath, ContentType.Json, "DELETE", null, String.format("/%s/operations/", subscriptionId)); } catch (Throwable ignored) { } String appPath = String.format("/%s/applications/%smobileservice", subscriptionId, mobileServiceName); try { executePollRequest(subscriptionId, appPath, ContentType.Xml, "DELETE", null, String.format("/%s/operations/", subscriptionId)); } catch (Throwable ignored) { } } @NotNull @Override public List<Table> getTableList(@NotNull String subscriptionId, @NotNull String mobileServiceName) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/tables", subscriptionId, mobileServiceName); String json = executeGetRequest(subscriptionId, path); Type type = new TypeToken<ArrayList<TableData>>() { }.getType(); List<TableData> tempRes = new Gson().fromJson(json, type); List<Table> res = new ArrayList<Table>(); for (TableData item : tempRes) { Table t = new Table(); t.setName(item.getName()); t.setSelfLink(item.getSelflink()); res.add(t); } return res; } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error getting table list", t); } } @Override public void createTable(@NotNull String subscriptionId, @NotNull String mobileServiceName, @NotNull String tableName, @NotNull TablePermissions permissions) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/tables", subscriptionId, mobileServiceName); String postData = "{\"insert\":\"" + PermissionItem.getPermitionString(permissions.getInsert()) + "\",\"read\":\"" + PermissionItem.getPermitionString(permissions.getRead()) + "\",\"update\":\"" + PermissionItem.getPermitionString(permissions.getUpdate()) + "\",\"delete\":\"" + PermissionItem.getPermitionString(permissions.getDelete()) + "\",\"name\":\"" + tableName + "\",\"idType\":\"string\"}"; executeRequest(subscriptionId, path, ContentType.Json, "POST", postData); } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error creating table", t); } } @Override public void updateTable(@NotNull String subscriptionId, @NotNull String mobileServiceName, @NotNull String tableName, @NotNull TablePermissions permissions) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/tables/%s/permissions", subscriptionId, mobileServiceName, tableName); String postData = "{\"insert\":\"" + PermissionItem.getPermitionString(permissions.getInsert()) + "\",\"read\":\"" + PermissionItem.getPermitionString(permissions.getRead()) + "\",\"update\":\"" + PermissionItem.getPermitionString(permissions.getUpdate()) + "\",\"delete\":\"" + PermissionItem.getPermitionString(permissions.getDelete()) + "\"}"; executeRequest(subscriptionId, path, ContentType.Json, "PUT", postData); } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error updating table", t); } } @NotNull @Override public Table showTableDetails(@NotNull String subscriptionId, @NotNull String mobileServiceName, @NotNull String tableName) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/tables/%s", subscriptionId, mobileServiceName, tableName); String json = executeGetRequest(subscriptionId, path); Gson gson = new Gson(); TableData tempRes = gson.fromJson(json, TableData.class); Table t = new Table(); t.setName(tempRes.getName()); t.setSelfLink(tempRes.getSelflink()); TablePermissionsData restTablePermissions = gson .fromJson(executeGetRequest(subscriptionId, path + "/permissions"), TablePermissionsData.class); TablePermissions tablePermissions = new TablePermissions(); tablePermissions.setInsert(PermissionItem.getPermitionType(restTablePermissions.getInsert())); tablePermissions.setUpdate(PermissionItem.getPermitionType(restTablePermissions.getUpdate())); tablePermissions.setRead(PermissionItem.getPermitionType(restTablePermissions.getRead())); tablePermissions.setDelete(PermissionItem.getPermitionType(restTablePermissions.getDelete())); t.setTablePermissions(tablePermissions); Type colType = new TypeToken<ArrayList<TableColumnData>>() { }.getType(); List<TableColumnData> colList = gson.fromJson(executeGetRequest(subscriptionId, path + "/columns"), colType); if (colList != null) { for (TableColumnData column : colList) { Column c = new Column(); c.setName(column.getName()); c.setType(column.getType()); c.setSelfLink(column.getSelflink()); c.setIndexed(column.isIndexed()); c.setZumoIndex(column.isZumoIndex()); t.getColumns().add(c); } } Type scrType = new TypeToken<ArrayList<TableScriptData>>() { }.getType(); List<TableScriptData> scrList = gson.fromJson(executeGetRequest(subscriptionId, path + "/scripts"), scrType); if (scrList != null) { for (TableScriptData script : scrList) { Script s = new Script(); s.setOperation(script.getOperation()); s.setBytes(script.getSizeBytes()); s.setSelfLink(script.getSelflink()); s.setName(String.format("%s.%s", tempRes.getName(), script.getOperation())); t.getScripts().add(s); } } return t; } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error getting table data", t); } } @Override public void downloadTableScript(@NotNull String subscriptionId, @NotNull String mobileServiceName, @NotNull String scriptName, @NotNull String downloadPath) throws AzureCmdException { try { String tableName = scriptName.split("\\.")[0]; String operation = scriptName.split("\\.")[1]; String path = String.format("/%s/services/mobileservices/mobileservices/%s/tables/%s/scripts/%s/code", subscriptionId, mobileServiceName, tableName, operation); String script = executeGetRequest(subscriptionId, path); Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(downloadPath), "utf-8")); writer.write(script); writer.flush(); writer.close(); } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error download script", t); } } @Override public void uploadTableScript(@NotNull String subscriptionId, @NotNull String mobileServiceName, @NotNull String scriptName, @NotNull String filePath) throws AzureCmdException { try { String tableName = scriptName.split("\\.")[0]; String operation = scriptName.split("\\.")[1]; String path = String.format("/%s/services/mobileservices/mobileservices/%s/tables/%s/scripts/%s/code", subscriptionId, mobileServiceName, tableName, operation); String file = readFile(filePath); executeRequest(subscriptionId, path, ContentType.Text, "PUT", file); } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error upload script", t); } } @NotNull @Override public List<CustomAPI> getAPIList(@NotNull String subscriptionId, @NotNull String mobileServiceName) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/apis", subscriptionId, mobileServiceName); String json = executeGetRequest(subscriptionId, path); Type type = new TypeToken<ArrayList<CustomAPIData>>() { }.getType(); List<CustomAPIData> tempRes = new Gson().fromJson(json, type); List<CustomAPI> res = new ArrayList<CustomAPI>(); for (CustomAPIData item : tempRes) { CustomAPI c = new CustomAPI(); c.setName(item.getName()); CustomAPIPermissions permissions = new CustomAPIPermissions(); permissions.setPutPermission(PermissionItem.getPermitionType(item.getPut())); permissions.setPostPermission(PermissionItem.getPermitionType(item.getPost())); permissions.setGetPermission(PermissionItem.getPermitionType(item.getGet())); permissions.setDeletePermission(PermissionItem.getPermitionType(item.getDelete())); permissions.setPatchPermission(PermissionItem.getPermitionType(item.getPatch())); c.setCustomAPIPermissions(permissions); res.add(c); } return res; } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error getting API list", t); } } @Override public void downloadAPIScript(@NotNull String subscriptionId, @NotNull String mobileServiceName, @NotNull String scriptName, @NotNull String downloadPath) throws AzureCmdException { try { String apiName = scriptName.split("\\.")[0]; String path = String.format("/%s/services/mobileservices/mobileservices/%s/apis/%s/script", subscriptionId, mobileServiceName, apiName); String script = executeGetRequest(subscriptionId, path); Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(downloadPath), "utf-8")); writer.write(script); writer.flush(); writer.close(); } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error getting API list", t); } } @Override public void uploadAPIScript(@NotNull String subscriptionId, @NotNull String mobileServiceName, @NotNull String scriptName, @NotNull String filePath) throws AzureCmdException { try { String apiName = scriptName.split("\\.")[0]; String path = String.format("/%s/services/mobileservices/mobileservices/%s/apis/%s/script", subscriptionId, mobileServiceName, apiName); String file = readFile(filePath); executeRequest(subscriptionId, path, ContentType.Text, "PUT", file); } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error upload script", t); } } @Override public void createCustomAPI(@NotNull String subscriptionId, @NotNull String mobileServiceName, @NotNull String tableName, @NotNull CustomAPIPermissions permissions) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/apis", subscriptionId, mobileServiceName); String postData = "{\"get\":\"" + permissions.getGetPermission() + "\",\"put\":\"" + permissions.getPutPermission() + "\",\"post\":\"" + permissions.getPostPermission() + "\",\"patch\":\"" + permissions.getPatchPermission() + "\",\"delete\":\"" + permissions.getDeletePermission() + "\",\"name\":\"" + tableName + "\"}"; executeRequest(subscriptionId, path, ContentType.Json, "POST", postData); } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error creating API", t); } } @Override public void updateCustomAPI(@NotNull String subscriptionId, @NotNull String mobileServiceName, @NotNull String tableName, @NotNull CustomAPIPermissions permissions) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/apis/%s", subscriptionId, mobileServiceName, tableName); String postData = "{\"get\":\"" + permissions.getGetPermission() + "\",\"put\":\"" + permissions.getPutPermission() + "\",\"post\":\"" + permissions.getPostPermission() + "\",\"patch\":\"" + permissions.getPatchPermission() + "\",\"delete\":\"" + permissions.getDeletePermission() + "\"}"; executeRequest(subscriptionId, path, ContentType.Json, "PUT", postData); } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error updating API", t); } } @Override public void deleteTable(@NotNull String subscriptionId, @NotNull String mobileServiceName, @NotNull String tableName) throws AzureCmdException { String path = String.format("/%s/services/mobileservices/mobileservices/%s/tables/%s", subscriptionId, mobileServiceName, tableName); try { executeRequest(subscriptionId, path, ContentType.Xml, "DELETE", null); } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error deleting table", t); } } @Override public void deleteCustomApi(@NotNull String subscriptionId, @NotNull String mobileServiceName, @NotNull String apiName) throws AzureCmdException { String path = String.format("/%s/services/mobileservices/mobileservices/%s/apis/%s", subscriptionId, mobileServiceName, apiName); try { executeRequest(subscriptionId, path, ContentType.Xml, "DELETE", null); } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error deleting API", t); } } @Override public void deleteJob(@NotNull String subscriptionId, @NotNull String mobileServiceName, @NotNull String jobName) throws AzureCmdException { String path = String.format("/%s/services/mobileservices/mobileservices/%s/scheduler/jobs/%s", subscriptionId, mobileServiceName, jobName); try { executeRequest(subscriptionId, path, ContentType.Xml, "DELETE", null); } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error deleting job", t); } } @NotNull @Override public List<Job> listJobs(@NotNull String subscriptionId, @NotNull String mobileServiceName) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/scheduler/jobs", subscriptionId, mobileServiceName); String json = executeGetRequest(subscriptionId, path); Type type = new TypeToken<ArrayList<JobData>>() { }.getType(); List<JobData> tempRes = new Gson().fromJson(json, type); List<Job> res = new ArrayList<Job>(); for (JobData item : tempRes) { Job j = new Job(); j.setAppName(item.getAppName()); j.setName(item.getName()); j.setEnabled(item.getStatus().equals("enabled")); j.setId(UUID.fromString(item.getId())); if (item.getIntervalPeriod() > 0) { j.setIntervalPeriod(item.getIntervalPeriod()); j.setIntervalUnit(item.getIntervalUnit()); } res.add(j); } return res; } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error getting job list", t); } } @Override public void createJob(@NotNull String subscriptionId, @NotNull String mobileServiceName, @NotNull String jobName, int interval, @NotNull String intervalUnit, @NotNull String startDate) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/scheduler/jobs", subscriptionId, mobileServiceName); String postData = "{\"name\":\"" + jobName + "\"" + (intervalUnit .equals("none") ? "" : (",\"intervalUnit\":\"" + intervalUnit + "\",\"intervalPeriod\":" + String.valueOf(interval) + ",\"startTime\":\"" + startDate + "\"")) + "}"; executeRequest(subscriptionId, path, ContentType.Json, "POST", postData); } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error creating jobs", t); } } @Override public void updateJob(@NotNull String subscriptionId, @NotNull String mobileServiceName, @NotNull String jobName, int interval, @NotNull String intervalUnit, @NotNull String startDate, boolean enabled) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/scheduler/jobs/%s", subscriptionId, mobileServiceName, jobName); String postData = "{" + "\"status\":\"" + (enabled ? "enabled" : "disabled") + "\"" + (intervalUnit .equals("none") ? "" : (",\"intervalUnit\":\"" + intervalUnit + "\",\"intervalPeriod\":" + String.valueOf(interval) + ",\"startTime\":\"" + startDate + "\"")) + "}"; if (intervalUnit.equals("none")) { postData = "{\"status\":\"disabled\"}"; } executeRequest(subscriptionId, path, ContentType.Json, "PUT", postData); } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error updating job", t); } } @Override public void downloadJobScript(@NotNull String subscriptionId, @NotNull String mobileServiceName, @NotNull String scriptName, @NotNull String downloadPath) throws AzureCmdException { try { String jobName = scriptName.split("\\.")[0]; String path = String.format("/%s/services/mobileservices/mobileservices/%s/scheduler/jobs/%s/script", subscriptionId, mobileServiceName, jobName); String script = executeGetRequest(subscriptionId, path); Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(downloadPath), "utf-8")); writer.write(script); writer.flush(); writer.close(); } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error download script", t); } } @Override public void uploadJobScript(@NotNull String subscriptionId, @NotNull String mobileServiceName, @NotNull String scriptName, @NotNull String filePath) throws AzureCmdException { try { String jobName = scriptName.split("\\.")[0]; String path = String.format("/%s/services/mobileservices/mobileservices/%s/scheduler/jobs/%s/script", subscriptionId, mobileServiceName, jobName); String file = readFile(filePath); executeRequest(subscriptionId, path, ContentType.Text, "PUT", file); } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error upload script", t); } } @NotNull @Override public List<LogEntry> listLog(@NotNull String subscriptionId, @NotNull String mobileServiceName, @NotNull String runtime) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/logs?$top=10", subscriptionId, mobileServiceName); String json = executeGetRequest(subscriptionId, path); LogData tempRes = new Gson().fromJson(json, LogData.class); List<LogEntry> res = new ArrayList<LogEntry>(); for (LogData.LogEntry item : tempRes.getResults()) { LogEntry logEntry = new LogEntry(); logEntry.setMessage(item.getMessage()); logEntry.setSource(item.getSource()); logEntry.setType(item.getType()); SimpleDateFormat ISO8601DATEFORMAT; if (MobileService.NODE_RUNTIME.equals(runtime)) { ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); } else { ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH); } logEntry.setTimeCreated(ISO8601DATEFORMAT.parse(item.getTimeCreated())); res.add(logEntry); } return res; } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } throw new AzureCmdException("Error getting log", t); } } @NotNull @Override public List<CloudService> getCloudServices(@NotNull String subscriptionId) throws AzureCmdException { return requestComputeSDK(subscriptionId, AzureSDKHelper.getCloudServices(subscriptionId)); } @NotNull @Override public List<VirtualMachine> getVirtualMachines(@NotNull String subscriptionId) throws AzureCmdException { return requestComputeSDK(subscriptionId, AzureSDKHelper.getVirtualMachines(subscriptionId)); } @NotNull @Override public VirtualMachine refreshVirtualMachineInformation(@NotNull VirtualMachine vm) throws AzureCmdException { return requestComputeSDK(vm.getSubscriptionId(), AzureSDKHelper.refreshVirtualMachineInformation(vm)); } @Override public void startVirtualMachine(@NotNull VirtualMachine vm) throws AzureCmdException { requestComputeSDK(vm.getSubscriptionId(), AzureSDKHelper.startVirtualMachine(vm)); } @Override public void shutdownVirtualMachine(@NotNull VirtualMachine vm, boolean deallocate) throws AzureCmdException { requestComputeSDK(vm.getSubscriptionId(), AzureSDKHelper.shutdownVirtualMachine(vm, deallocate)); } @Override public void restartVirtualMachine(@NotNull VirtualMachine vm) throws AzureCmdException { requestComputeSDK(vm.getSubscriptionId(), AzureSDKHelper.restartVirtualMachine(vm)); } @Override public void deleteVirtualMachine(@NotNull VirtualMachine vm, boolean deleteFromStorage) throws AzureCmdException { requestComputeSDK(vm.getSubscriptionId(), AzureSDKHelper.deleteVirtualMachine(vm, deleteFromStorage)); } @NotNull @Override public byte[] downloadRDP(@NotNull VirtualMachine vm) throws AzureCmdException { return requestComputeSDK(vm.getSubscriptionId(), AzureSDKHelper.downloadRDP(vm)); } @NotNull @Override public List<StorageAccount> getStorageAccounts(@NotNull String subscriptionId, boolean detailed) throws AzureCmdException { return requestStorageSDK(subscriptionId, AzureSDKHelper.getStorageAccounts(subscriptionId, detailed)); } @NotNull @Override public Boolean checkStorageNameAvailability(@NotNull final String subscriptionId, final String storageAccountName) throws AzureCmdException { return requestStorageSDK(subscriptionId, AzureSDKHelper.checkStorageNameAvailability(storageAccountName)); } @NotNull @Override public List<VirtualMachineImage> getVirtualMachineImages(@NotNull String subscriptionId) throws AzureCmdException { return requestComputeSDK(subscriptionId, AzureSDKHelper.getVirtualMachineImages()); } @NotNull @Override public List<VirtualMachineSize> getVirtualMachineSizes(@NotNull String subscriptionId) throws AzureCmdException { return requestManagementSDK(subscriptionId, AzureSDKHelper.getVirtualMachineSizes()); } @NotNull @Override public List<Location> getLocations(@NotNull String subscriptionId) throws AzureCmdException { return requestManagementSDK(subscriptionId, AzureSDKHelper.getLocations()); } @NotNull @Override public List<AffinityGroup> getAffinityGroups(@NotNull String subscriptionId) throws AzureCmdException { return requestManagementSDK(subscriptionId, AzureSDKHelper.getAffinityGroups()); } @NotNull @Override public List<VirtualNetwork> getVirtualNetworks(@NotNull String subscriptionId) throws AzureCmdException { return requestNetworkSDK(subscriptionId, AzureSDKHelper.getVirtualNetworks(subscriptionId)); } @Override public OperationStatusResponse createStorageAccount(@NotNull StorageAccount storageAccount) throws AzureCmdException { return requestStorageSDK(storageAccount.getSubscriptionId(), AzureSDKHelper.createStorageAccount(storageAccount)); } @Override public void createCloudService(@NotNull CloudService cloudService) throws AzureCmdException { requestComputeSDK(cloudService.getSubscriptionId(), AzureSDKHelper.createCloudService(cloudService)); } @Override public CloudService getCloudServiceDetailed(@NotNull CloudService cloudService) throws AzureCmdException { return requestComputeSDK(cloudService.getSubscriptionId(), AzureSDKHelper.getCloudServiceDetailed(cloudService.getSubscriptionId(), cloudService.getName())); } @NotNull @Override public Boolean checkHostedServiceNameAvailability(@NotNull final String subscriptionId, final String hostedServiceName) throws AzureCmdException { return requestComputeSDK(subscriptionId, AzureSDKHelper.checkHostedServiceNameAvailability(hostedServiceName)); } @Override public void createVirtualMachine(@NotNull VirtualMachine virtualMachine, @NotNull VirtualMachineImage vmImage, @NotNull StorageAccount storageAccount, @NotNull String virtualNetwork, @NotNull String username, @NotNull String password, @NotNull byte[] certificate) throws AzureCmdException { requestComputeSDK(virtualMachine.getSubscriptionId(), AzureSDKHelper.createVirtualMachine(virtualMachine, vmImage, storageAccount, virtualNetwork, username, password, certificate)); } @Override public void createVirtualMachine(@NotNull VirtualMachine virtualMachine, @NotNull VirtualMachineImage vmImage, @NotNull String mediaLocation, @NotNull String virtualNetwork, @NotNull String username, @NotNull String password, @NotNull byte[] certificate) throws AzureCmdException { requestComputeSDK(virtualMachine.getSubscriptionId(), AzureSDKHelper.createVirtualMachine(virtualMachine, vmImage, mediaLocation, virtualNetwork, username, password, certificate)); } @Override public OperationStatusResponse createDeployment(@NotNull String subscriptionId, @NotNull String serviceName, @NotNull String slotName, @NotNull DeploymentCreateParameters parameters, @NotNull String unpublish) throws AzureCmdException { return requestComputeSDK(subscriptionId, AzureSDKHelper.createDeployment(serviceName, slotName, parameters, unpublish)); } @Override public OperationStatusResponse deleteDeployment(@NotNull String subscriptionId, @NotNull String serviceName, @NotNull String deploymentName, boolean deleteFromStorage) throws AzureCmdException { return requestComputeSDK(subscriptionId, AzureSDKHelper.deleteDeployment(serviceName, deploymentName, deleteFromStorage)); } public DeploymentGetResponse getDeploymentBySlot(@NotNull String subscriptionId, @NotNull String serviceName, @NotNull DeploymentSlot deploymentSlot) throws AzureCmdException { return requestComputeSDK(subscriptionId, AzureSDKHelper.getDeploymentBySlot(serviceName, deploymentSlot)); } @Override public OperationStatusResponse waitForStatus(@NotNull String subscriptionId, @NotNull OperationStatusResponse operationStatusResponse) throws AzureCmdException { return requestComputeSDK(subscriptionId, AzureSDKHelper.waitForStatus(operationStatusResponse)); } @NotNull @Override public StorageAccount refreshStorageAccountInformation(@NotNull StorageAccount storageAccount) throws AzureCmdException { return requestStorageSDK(storageAccount.getSubscriptionId(), AzureSDKHelper.refreshStorageAccountInformation(storageAccount)); } @Override public String createServiceCertificate(@NotNull String subscriptionId, @NotNull String serviceName, @NotNull byte[] data, @NotNull String password, boolean needThumbprint) throws AzureCmdException { return requestComputeSDK(subscriptionId, AzureSDKHelper.createServiceCertificate(serviceName, data, password, needThumbprint)); } @Override public List<ServiceCertificateListResponse.Certificate> getCertificates(@NotNull String subscriptionId, @NotNull String serviceName) throws AzureCmdException { return requestComputeSDK(subscriptionId, AzureSDKHelper.getCertificates(serviceName)); } @Override public void deleteStorageAccount(@NotNull StorageAccount storageAccount) throws AzureCmdException { requestStorageSDK(storageAccount.getSubscriptionId(), AzureSDKHelper.deleteStorageAccount(storageAccount)); } @Override public ResourceGroupExtended createResourceGroup(@NotNull String subscriptionId, @NotNull String name, @NotNull String location) throws AzureCmdException { return requestResourceManagementSDK(subscriptionId, AzureSDKHelper.createResourceGroup(name, location)); } @Override public List<String> getResourceGroupNames(@NotNull String subscriptionId) throws AzureCmdException { return requestResourceManagementSDK(subscriptionId, AzureSDKHelper.getResourceGroupNames()); } @NotNull @Override public List<WebSite> getWebSites(@NotNull String subscriptionId, @NotNull String webSpaceName) throws AzureCmdException { return requestWebSiteSDK(subscriptionId, AzureSDKHelper.getWebSites(webSpaceName)); } @NotNull @Override public List<WebHostingPlanCache> getWebHostingPlans(@NotNull String subscriptionId, @NotNull String webSpaceName) throws AzureCmdException { return requestWebSiteSDK(subscriptionId, AzureSDKHelper.getWebHostingPlans(webSpaceName)); } @NotNull @Override public WebSiteConfiguration getWebSiteConfiguration(@NotNull String subscriptionId, @NotNull String webSpaceName, @NotNull String webSiteName) throws AzureCmdException { return requestWebSiteSDK(subscriptionId, AzureSDKHelper.getWebSiteConfiguration(webSpaceName, webSiteName)); } @NotNull @Override public WebSitePublishSettings getWebSitePublishSettings(@NotNull String subscriptionId, @NotNull String webSpaceName, @NotNull String webSiteName) throws AzureCmdException { return requestWebSiteSDK(subscriptionId, AzureSDKHelper.getWebSitePublishSettings(webSpaceName, webSiteName)); } @Override public void restartWebSite(@NotNull String subscriptionId, @NotNull String webSpaceName, @NotNull String webSiteName) throws AzureCmdException { requestWebSiteSDK(subscriptionId, AzureSDKHelper.restartWebSite(webSpaceName, webSiteName)); } @Override public void stopWebSite(@NotNull String subscriptionId, @NotNull String webSpaceName, @NotNull String webSiteName) throws AzureCmdException { requestWebSiteSDK(subscriptionId, AzureSDKHelper.stopWebSite(webSpaceName, webSiteName)); } @Override public void startWebSite(@NotNull String subscriptionId, @NotNull String webSpaceName, @NotNull String webSiteName) throws AzureCmdException { requestWebSiteSDK(subscriptionId, AzureSDKHelper.startWebSite(webSpaceName, webSiteName)); } @NotNull @Override public WebSite createWebSite(@NotNull String subscriptionId, @NotNull WebHostingPlanCache webHostingPlan, @NotNull String webSiteName) throws AzureCmdException { return requestWebSiteSDK(subscriptionId, AzureSDKHelper.createWebSite(webHostingPlan, webSiteName)); } @Override public WebSite getWebSite(@NotNull String subscriptionId, @NotNull final String webSpaceName, @NotNull String webSiteName) throws AzureCmdException { return requestWebSiteSDK(subscriptionId, AzureSDKHelper.getWebSite(webSpaceName, webSiteName)); } @NotNull @Override public WebSiteConfiguration updateWebSiteConfiguration(@NotNull String subscriptionId, @NotNull String webSpaceName, @NotNull String webSiteName, @NotNull String location, @NotNull WebSiteConfiguration webSiteConfiguration) throws AzureCmdException { return requestWebSiteSDK(subscriptionId, AzureSDKHelper.updateWebSiteConfiguration(webSpaceName, webSiteName, location, webSiteConfiguration)); } @NotNull @Override public WebHostingPlan createWebHostingPlan(@NotNull String subscriptionId, @NotNull WebHostingPlanCache webHostingPlan) throws AzureCmdException { return requestWebSiteSDK(subscriptionId, AzureSDKHelper.createWebHostingPlan(webHostingPlan)); } @Nullable @Override public ArtifactDescriptor getWebArchiveArtifact(@NotNull ProjectDescriptor projectDescriptor) throws AzureCmdException { ArtifactDescriptor artifactDescriptor = null; for (ArtifactDescriptor descriptor : DefaultLoader.getIdeHelper().getArtifacts(projectDescriptor)) { if ("war".equals(descriptor.getArtifactType())) { artifactDescriptor = descriptor; break; } } return artifactDescriptor; } @Override public void deployWebArchiveArtifact(@NotNull final ProjectDescriptor projectDescriptor, @NotNull final ArtifactDescriptor artifactDescriptor, @NotNull final WebSite webSite, @NotNull final boolean isDeployRoot) { ListenableFuture<String> future = DefaultLoader.getIdeHelper().buildArtifact(projectDescriptor, artifactDescriptor); Futures.addCallback(future, new FutureCallback<String>() { @Override public void onSuccess(final String artifactPath) { try { DefaultLoader.getIdeHelper().runInBackground(projectDescriptor, "Deploying web app", "Deploying web app...", new CancellableTask() { @Override public void run(CancellationHandle cancellationHandle) throws Throwable { AzureManager manager = AzureManagerImpl.getManager(); manager.publishWebArchiveArtifact(webSite.getSubscriptionId(), webSite.getWebSpaceName(), webSite.getName(), artifactPath, isDeployRoot, artifactDescriptor.getName()); } @Override public void onCancel() { } @Override public void onSuccess() { } @Override public void onError(@NotNull Throwable throwable) { DefaultLoader.getUIHelper().showException( "An error occurred while attempting to deploy web app.", throwable, "MS Services - Error Deploying Web App", false, true); } }); } catch (AzureCmdException ex) { DefaultLoader.getUIHelper().showException( "An error occurred while attempting to deploy web app.", ex, "MS Services - Error Deploying Web App", false, true); } } @Override public void onFailure(Throwable throwable) { DefaultLoader.getUIHelper().showException( "An error occurred while attempting to build web archive artifact.", throwable, "MS Services - Error Building WAR Artifact", false, true); } }); } @Override public void publishWebArchiveArtifact(@NotNull String subscriptionId, @NotNull String webSpaceName, @NotNull String webSiteName, @NotNull String artifactPath, @NotNull boolean isDeployRoot, @NotNull String artifactName) throws AzureCmdException { WebSitePublishSettings webSitePublishSettings = getWebSitePublishSettings(subscriptionId, webSpaceName, webSiteName); WebSitePublishSettings.FTPPublishProfile publishProfile = null; for (PublishProfile pp : webSitePublishSettings.getPublishProfileList()) { if (pp instanceof FTPPublishProfile) { publishProfile = (FTPPublishProfile) pp; break; } } if (publishProfile == null) { throw new AzureCmdException("Unable to retrieve FTP credentials to publish web site"); } URI uri; try { uri = new URI(publishProfile.getPublishUrl()); } catch (URISyntaxException e) { throw new AzureCmdException("Unable to parse FTP Publish Url information", e); } final FTPClient ftp = new FTPClient(); try { ftp.connect(uri.getHost()); final int replyCode = ftp.getReplyCode(); if (!FTPReply.isPositiveCompletion(replyCode)) { ftp.disconnect(); throw new AzureCmdException("Unable to connect to FTP server"); } if (!ftp.login(publishProfile.getUserName(), publishProfile.getPassword())) { ftp.logout(); throw new AzureCmdException("Unable to login to FTP server"); } ftp.setFileType(FTP.BINARY_FILE_TYPE); if (publishProfile.isFtpPassiveMode()) { ftp.enterLocalPassiveMode(); } String targetDir = getAbsolutePath(uri.getPath()); targetDir += "/webapps"; InputStream input = new FileInputStream(artifactPath); if (isDeployRoot) { ftp.storeFile(targetDir + "/ROOT.war", input); } else { ftp.storeFile(targetDir + "/" + artifactName + ".war", input); } input.close(); ftp.logout(); } catch (IOException e) { throw new AzureCmdException("Unable to connect to the FTP server", e); } finally { if (ftp.isConnected()) { try { ftp.disconnect(); } catch (IOException ignored) { } } } } private void loadSubscriptions() { String json = DefaultLoader.getIdeHelper().getProperty(AppSettingsNames.AZURE_SUBSCRIPTIONS); if (!StringHelper.isNullOrWhiteSpace(json)) { try { Type subscriptionsType = new TypeToken<HashMap<String, Subscription>>() { }.getType(); subscriptions = gson.fromJson(json, subscriptionsType); } catch (JsonSyntaxException ignored) { DefaultLoader.getIdeHelper().unsetProperty(AppSettingsNames.AZURE_SUBSCRIPTIONS); } } else { subscriptions = new HashMap<String, Subscription>(); } for (String subscriptionId : subscriptions.keySet()) { lockBySubscriptionId.put(subscriptionId, new ReentrantReadWriteLock(false)); } } private void loadUserInfo() { String json = DefaultLoader.getIdeHelper().getProperty(AppSettingsNames.AZURE_USER_INFO); if (!StringHelper.isNullOrWhiteSpace(json)) { try { userInfo = gson.fromJson(json, UserInfo.class); } catch (JsonSyntaxException ignored) { DefaultLoader.getIdeHelper().unsetProperty(AppSettingsNames.AZURE_USER_INFO); DefaultLoader.getIdeHelper().unsetProperty(AppSettingsNames.AZURE_USER_SUBSCRIPTIONS); } } else { DefaultLoader.getIdeHelper().unsetProperty(AppSettingsNames.AZURE_USER_SUBSCRIPTIONS); } json = DefaultLoader.getIdeHelper().getProperty(AppSettingsNames.AZURE_USER_SUBSCRIPTIONS); if (!StringHelper.isNullOrWhiteSpace(json)) { try { Type userInfoBySubscriptionIdType = new TypeToken<HashMap<String, UserInfo>>() { }.getType(); userInfoBySubscriptionId = gson.fromJson(json, userInfoBySubscriptionIdType); } catch (JsonSyntaxException ignored) { DefaultLoader.getIdeHelper().unsetProperty(AppSettingsNames.AZURE_USER_SUBSCRIPTIONS); } } else { userInfoBySubscriptionId = new HashMap<String, UserInfo>(); } } private void loadSSLSocketFactory() { sslSocketFactoryBySubscriptionId = new HashMap<String, SSLSocketFactory>(); for (Map.Entry<String, Subscription> subscriptionEntry : subscriptions.entrySet()) { String subscriptionId = subscriptionEntry.getKey(); Subscription subscription = subscriptionEntry.getValue(); String managementCertificate = subscription.getManagementCertificate(); if (!StringHelper.isNullOrWhiteSpace(managementCertificate)) { try { SSLSocketFactory sslSocketFactory = initSSLSocketFactory(managementCertificate); sslSocketFactoryBySubscriptionId.put(subscriptionId, sslSocketFactory); } catch (Exception e) { subscription.setManagementCertificate(null); } } } } private void removeInvalidUserInfo() { List<String> invalidSubscriptionIds = new ArrayList<String>(); for (String subscriptionId : userInfoBySubscriptionId.keySet()) { if (!subscriptions.containsKey(subscriptionId)) { invalidSubscriptionIds.add(subscriptionId); } } for (String invalidSubscriptionId : invalidSubscriptionIds) { userInfoBySubscriptionId.remove(invalidSubscriptionId); } } private void removeUnusedSubscriptions() { List<String> invalidSubscriptionIds = new ArrayList<String>(); for (Map.Entry<String, Subscription> subscriptionEntry : subscriptions.entrySet()) { String subscriptionId = subscriptionEntry.getKey(); Subscription subscription = subscriptionEntry.getValue(); if (!userInfoBySubscriptionId.containsKey(subscriptionId) && !sslSocketFactoryBySubscriptionId.containsKey(subscriptionId)) { invalidSubscriptionIds.add(subscriptionId); } else if (!userInfoBySubscriptionId.containsKey(subscriptionId)) { subscription.setTenantId(null); } else if (!sslSocketFactoryBySubscriptionId.containsKey(subscriptionId)) { subscription.setManagementCertificate(null); subscription.setServiceManagementUrl(null); } } for (String invalidSubscriptionId : invalidSubscriptionIds) { lockBySubscriptionId.remove(invalidSubscriptionId); subscriptions.remove(invalidSubscriptionId); } } private void storeSubscriptions() { Type subscriptionsType = new TypeToken<HashMap<String, Subscription>>() { }.getType(); String json = gson.toJson(subscriptions, subscriptionsType); DefaultLoader.getIdeHelper().setProperty(AppSettingsNames.AZURE_SUBSCRIPTIONS, json); } private void storeUserInfo() { String json = gson.toJson(userInfo, UserInfo.class); DefaultLoader.getIdeHelper().setProperty(AppSettingsNames.AZURE_USER_INFO, json); Type userInfoBySubscriptionIdType = new TypeToken<HashMap<String, UserInfo>>() { }.getType(); json = gson.toJson(userInfoBySubscriptionId, userInfoBySubscriptionIdType); DefaultLoader.getIdeHelper().setProperty(AppSettingsNames.AZURE_USER_SUBSCRIPTIONS, json); } @NotNull private List<Subscription> parseSubscriptionsXML(@NotNull String subscriptionsXML) throws SAXException, ParserConfigurationException, XPathExpressionException, IOException { NodeList subscriptionList = (NodeList) XmlHelper.getXMLValue(subscriptionsXML, "//Subscription", XPathConstants.NODESET); ArrayList<Subscription> subscriptions = new ArrayList<Subscription>(); for (int i = 0; i < subscriptionList.getLength(); i++) { Subscription subscription = new Subscription(); subscription.setName(XmlHelper.getChildNodeValue(subscriptionList.item(i), "SubscriptionName")); subscription.setId(XmlHelper.getChildNodeValue(subscriptionList.item(i), "SubscriptionID")); subscription.setTenantId(XmlHelper.getChildNodeValue(subscriptionList.item(i), "AADTenantID")); subscription.setMaxStorageAccounts( Integer.valueOf(XmlHelper.getChildNodeValue(subscriptionList.item(i), "MaxStorageAccounts"))); subscription.setMaxHostedServices( Integer.valueOf(XmlHelper.getChildNodeValue(subscriptionList.item(i), "MaxHostedServices"))); subscription.setSelected(true); subscriptions.add(subscription); } return subscriptions; } private SSLSocketFactory initSSLSocketFactory(@NotNull String managementCertificate) throws NoSuchAlgorithmException, IOException, KeyStoreException, CertificateException, UnrecoverableKeyException, KeyManagementException { byte[] decodeBuffer = new BASE64Decoder().decodeBuffer(managementCertificate); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509"); InputStream is = new ByteArrayInputStream(decodeBuffer); KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(is, OpenSSLHelper.PASSWORD.toCharArray()); keyManagerFactory.init(ks, OpenSSLHelper.PASSWORD.toCharArray()); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom()); return sslContext.getSocketFactory(); } private List<Subscription> importSubscription(@NotNull String publishSettingsFilePath) throws AzureCmdException { try { StringBuilder sb = new StringBuilder(); BufferedReader br = new BufferedReader(new FileReader(publishSettingsFilePath)); String line = br.readLine(); while (line != null) { sb.append(line); line = br.readLine(); } // String subscriptionFile = OpenSSLHelper.processCertificate(sb.toString()); String publishSettingsFile = sb.toString(); String managementCertificate = null; String serviceManagementUrl = null; boolean isPublishSettings2 = true; Node publishProfile = (Node) XmlHelper.getXMLValue(publishSettingsFile, "//PublishProfile", XPathConstants.NODE); if (XmlHelper.getAttributeValue(publishProfile, "SchemaVersion") == null || !XmlHelper.getAttributeValue(publishProfile, "SchemaVersion").equals("2.0")) { isPublishSettings2 = false; managementCertificate = XmlHelper.getAttributeValue(publishProfile, "ManagementCertificate"); serviceManagementUrl = XmlHelper.getAttributeValue(publishProfile, "Url"); } NodeList subscriptionNodes = (NodeList) XmlHelper.getXMLValue(publishSettingsFile, "//Subscription", XPathConstants.NODESET); List<Subscription> subscriptions = new ArrayList<Subscription>(); for (int i = 0; i < subscriptionNodes.getLength(); i++) { Node subscriptionNode = subscriptionNodes.item(i); Subscription subscription = new Subscription(); subscription.setName(XmlHelper.getAttributeValue(subscriptionNode, "Name")); subscription.setId(XmlHelper.getAttributeValue(subscriptionNode, "Id")); if (isPublishSettings2) { subscription.setManagementCertificate( XmlHelper.getAttributeValue(subscriptionNode, "ManagementCertificate")); subscription.setServiceManagementUrl( XmlHelper.getAttributeValue(subscriptionNode, "ServiceManagementUrl")); } else { subscription.setManagementCertificate(managementCertificate); subscription.setServiceManagementUrl(serviceManagementUrl); } subscription.setSelected(true); Configuration config = AzureSDKHelper.getConfiguration(new File(publishSettingsFilePath), subscription.getId()); SubscriptionGetResponse response = WindowsAzureRestUtils.getSubscription(config); com.microsoftopentechnologies.azuremanagementutil.model.Subscription sub = SubscriptionTransformer .transform(response); subscription.setMaxStorageAccounts(sub.getMaxStorageAccounts()); subscription.setMaxHostedServices(sub.getMaxHostedServices()); subscriptions.add(subscription); } return subscriptions; } catch (Exception ex) { if (ex instanceof AzureCmdException) { throw (AzureCmdException) ex; } throw new AzureCmdException("Error importing subscriptions from publish settings file", ex); } } private void updateSubscription(@NotNull Subscription subscription, @NotNull UserInfo userInfo) throws AzureCmdException { authDataLock.readLock().lock(); try { String subscriptionId = subscription.getId(); ReentrantReadWriteLock subscriptionLock = getSubscriptionLock(subscriptionId, true); subscriptionLock.writeLock().lock(); try { if (subscriptions.containsKey(subscriptionId)) { subscriptions.get(subscriptionId).setTenantId(subscription.getTenantId()); } else { subscriptions.put(subscriptionId, subscription); } setUserInfo(subscriptionId, userInfo); storeSubscriptions(); } finally { subscriptionLock.writeLock().unlock(); } } finally { authDataLock.readLock().unlock(); } } private void updateSubscription(@NotNull Subscription subscription, @NotNull SSLSocketFactory sslSocketFactory) throws AzureCmdException { authDataLock.readLock().lock(); try { String subscriptionId = subscription.getId(); ReentrantReadWriteLock subscriptionLock = getSubscriptionLock(subscriptionId, true); subscriptionLock.writeLock().lock(); try { if (subscriptions.containsKey(subscriptionId)) { Subscription existingSubscription = subscriptions.get(subscriptionId); existingSubscription.setManagementCertificate(subscription.getManagementCertificate()); existingSubscription.setServiceManagementUrl(subscription.getServiceManagementUrl()); } else { subscriptions.put(subscriptionId, subscription); } setSSLSocketFactory(subscriptionId, sslSocketFactory); storeSubscriptions(); } finally { subscriptionLock.writeLock().unlock(); } } finally { authDataLock.readLock().unlock(); } } private void notifySubscriptionsChanged() { subscriptionsChangedLock.readLock().lock(); try { for (EventWaitHandleImpl handle : subscriptionsChangedHandles) { handle.signalEvent(); } } finally { subscriptionsChangedLock.readLock().unlock(); } } @Nullable public UserInfo getUserInfo() { authDataLock.readLock().lock(); try { return userInfo; } finally { authDataLock.readLock().unlock(); } } private void setUserInfo(@Nullable UserInfo userInfo) { authDataLock.writeLock().lock(); try { this.userInfo = userInfo; userInfoBySubscriptionId.clear(); removeUnusedSubscriptions(); storeSubscriptions(); storeUserInfo(); } finally { authDataLock.writeLock().unlock(); } } @NotNull private Subscription getSubscription(@NotNull String subscriptionId) throws AzureCmdException { authDataLock.readLock().lock(); try { ReentrantReadWriteLock subscriptionLock = getSubscriptionLock(subscriptionId, false); subscriptionLock.readLock().lock(); try { return subscriptions.get(subscriptionId); } finally { subscriptionLock.readLock().unlock(); } } finally { authDataLock.readLock().unlock(); } } private boolean hasUserInfo(@NotNull String subscriptionId) { authDataLock.readLock().lock(); try { Optional<ReentrantReadWriteLock> optionalRWLock = getSubscriptionLock(subscriptionId); if (!optionalRWLock.isPresent()) { return false; } ReentrantReadWriteLock subscriptionLock = optionalRWLock.get(); subscriptionLock.readLock().lock(); try { return userInfoBySubscriptionId.containsKey(subscriptionId); } finally { subscriptionLock.readLock().unlock(); } } finally { authDataLock.readLock().unlock(); } } @NotNull private UserInfo getUserInfo(@NotNull String subscriptionId) throws AzureCmdException { authDataLock.readLock().lock(); try { ReentrantReadWriteLock subscriptionLock = getSubscriptionLock(subscriptionId, false); subscriptionLock.readLock().lock(); try { if (!userInfoBySubscriptionId.containsKey(subscriptionId)) { throw new AzureCmdException("No User Information for the specified Subscription Id"); } return userInfoBySubscriptionId.get(subscriptionId); } finally { subscriptionLock.readLock().unlock(); } } finally { authDataLock.readLock().unlock(); } } private void setUserInfo(@NotNull String subscriptionId, @NotNull UserInfo userInfo) throws AzureCmdException { authDataLock.readLock().lock(); try { ReentrantReadWriteLock subscriptionLock = getSubscriptionLock(subscriptionId, true); subscriptionLock.writeLock().lock(); try { userInfoBySubscriptionId.put(subscriptionId, userInfo); storeUserInfo(); } finally { subscriptionLock.writeLock().unlock(); } } finally { authDataLock.readLock().unlock(); } } public String getAccessToken(String subscriptionId) { authDataLock.readLock().lock(); try { ReentrantReadWriteLock subscriptionLock = getSubscriptionLock(subscriptionId, false); subscriptionLock.readLock().lock(); try { if (!userInfoBySubscriptionId.containsKey(subscriptionId)) { return ""; } UserInfo userInfo = userInfoBySubscriptionId.get(subscriptionId); return getAccessToken(userInfo); } finally { subscriptionLock.readLock().unlock(); } } catch (AzureCmdException ex) { // return empty string return ""; } finally { authDataLock.readLock().unlock(); } } private boolean hasSSLSocketFactory(@NotNull String subscriptionId) { authDataLock.readLock().lock(); try { Optional<ReentrantReadWriteLock> optionalRWLock = getSubscriptionLock(subscriptionId); if (!optionalRWLock.isPresent()) { return false; } ReentrantReadWriteLock subscriptionLock = optionalRWLock.get(); subscriptionLock.readLock().lock(); try { return sslSocketFactoryBySubscriptionId.containsKey(subscriptionId); } finally { subscriptionLock.readLock().unlock(); } } finally { authDataLock.readLock().unlock(); } } @NotNull private Optional<SSLSocketFactory> getSSLSocketFactory(@NotNull String subscriptionId) throws AzureCmdException { authDataLock.readLock().lock(); try { ReentrantReadWriteLock subscriptionLock = getSubscriptionLock(subscriptionId, false); subscriptionLock.readLock().lock(); try { if (!sslSocketFactoryBySubscriptionId.containsKey(subscriptionId)) { return Optional.absent(); } return Optional.of(sslSocketFactoryBySubscriptionId.get(subscriptionId)); } finally { subscriptionLock.readLock().unlock(); } } finally { authDataLock.readLock().unlock(); } } private void setSSLSocketFactory(@NotNull String subscriptionId, @NotNull SSLSocketFactory sslSocketFactory) throws AzureCmdException { authDataLock.readLock().lock(); try { ReentrantReadWriteLock subscriptionLock = getSubscriptionLock(subscriptionId, true); subscriptionLock.writeLock().lock(); try { sslSocketFactoryBySubscriptionId.put(subscriptionId, sslSocketFactory); } finally { subscriptionLock.writeLock().unlock(); } } finally { authDataLock.readLock().unlock(); } } private boolean hasAccessToken(@NotNull UserInfo userInfo) { authDataLock.readLock().lock(); try { Optional<ReentrantReadWriteLock> optionalRWLock = getUserLock(userInfo); if (!optionalRWLock.isPresent()) { return false; } ReadWriteLock userLock = optionalRWLock.get(); userLock.readLock().lock(); try { return accessTokenByUser.containsKey(userInfo); } finally { userLock.readLock().unlock(); } } finally { authDataLock.readLock().unlock(); } } @NotNull private String getAccessToken(@NotNull UserInfo userInfo) throws AzureCmdException { authDataLock.readLock().lock(); try { ReentrantReadWriteLock userLock = getUserLock(userInfo, false); userLock.readLock().lock(); try { if (!accessTokenByUser.containsKey(userInfo)) { throw new AzureCmdException("No access token for the specified User Information", ""); } return accessTokenByUser.get(userInfo); } finally { userLock.readLock().unlock(); } } finally { authDataLock.readLock().unlock(); } } private void setAccessToken(@NotNull UserInfo userInfo, @NotNull String accessToken) throws AzureCmdException { authDataLock.readLock().lock(); try { ReentrantReadWriteLock userLock = getUserLock(userInfo, true); userLock.writeLock().lock(); try { accessTokenByUser.put(userInfo, accessToken); } finally { userLock.writeLock().unlock(); } } finally { authDataLock.readLock().unlock(); } } private boolean hasAccessToken() { authDataLock.readLock().lock(); try { return !(accessToken == null || accessToken.isEmpty()); } finally { authDataLock.readLock().unlock(); } } @NotNull private ReentrantReadWriteLock getSubscriptionLock(@NotNull String subscriptionId, boolean createOnMissing) throws AzureCmdException { Lock lock = createOnMissing ? subscriptionMapLock.writeLock() : subscriptionMapLock.readLock(); lock.lock(); try { if (!lockBySubscriptionId.containsKey(subscriptionId)) { if (createOnMissing) { lockBySubscriptionId.put(subscriptionId, new ReentrantReadWriteLock(false)); } else { throw new AzureCmdException("No authentication information for the specified Subscription Id"); } } return lockBySubscriptionId.get(subscriptionId); } finally { lock.unlock(); } } @NotNull private Optional<ReentrantReadWriteLock> getSubscriptionLock(@NotNull String subscriptionId) { subscriptionMapLock.readLock().lock(); try { if (lockBySubscriptionId.containsKey(subscriptionId)) { return Optional.of(lockBySubscriptionId.get(subscriptionId)); } else { return Optional.absent(); } } finally { subscriptionMapLock.readLock().unlock(); } } @NotNull private ReentrantReadWriteLock getUserLock(@NotNull UserInfo userInfo, boolean createOnMissing) throws AzureCmdException { Lock lock = createOnMissing ? userMapLock.writeLock() : userMapLock.readLock(); lock.lock(); try { if (!lockByUser.containsKey(userInfo)) { if (createOnMissing) { lockByUser.put(userInfo, new ReentrantReadWriteLock(false)); } else { throw new AzureCmdException("No access token for the specified User Information"); } } return lockByUser.get(userInfo); } finally { lock.unlock(); } } @NotNull private Optional<ReentrantReadWriteLock> getUserLock(@NotNull UserInfo userInfo) { userMapLock.readLock().lock(); try { if (lockByUser.containsKey(userInfo)) { return Optional.of(lockByUser.get(userInfo)); } else { return Optional.absent(); } } finally { userMapLock.readLock().unlock(); } } @NotNull private String executeGetRequest(@NotNull String subscriptionId, @NotNull String path) throws AzureCmdException { return executeRequest(subscriptionId, path, ContentType.Json, "GET", null); } @NotNull private String executeRequest(@NotNull String subscriptionId, @NotNull final String path, @NotNull final ContentType contentType, @NotNull final String method, @Nullable final String postData) throws AzureCmdException { Subscription subscription = getSubscription(subscriptionId); Optional<SSLSocketFactory> optionalSSLSocketFactory = getSSLSocketFactory(subscriptionId); if (optionalSSLSocketFactory.isPresent()) { SSLSocketFactory sslSocketFactory = optionalSSLSocketFactory.get(); return AzureCertificateHelper.executeRequest(subscription.getServiceManagementUrl(), path, contentType, method, postData, sslSocketFactory, MobileServiceRestManager.getManager()); } else { final PluginSettings settings = DefaultLoader.getPluginComponent().getSettings(); final String managementUri = settings.getAzureServiceManagementUri(); final UserInfo userInfo = getUserInfo(subscriptionId); return requestWithToken(userInfo, new RequestCallback<String>() { @Override public String execute() throws Throwable { String accessToken = getAccessToken(userInfo); return AzureAADHelper.executeRequest(managementUri, path, contentType, method, postData, accessToken, MobileServiceRestManager.getManager()); } }); } } @NotNull private String executePollRequest(@NotNull String subscriptionId, @NotNull final String path, @NotNull final ContentType contentType, @NotNull final String method, @Nullable final String postData, @NotNull final String pollPath) throws AzureCmdException { Subscription subscription = getSubscription(subscriptionId); Optional<SSLSocketFactory> optionalSSLSocketFactory = getSSLSocketFactory(subscriptionId); if (optionalSSLSocketFactory.isPresent()) { SSLSocketFactory sslSocketFactory = optionalSSLSocketFactory.get(); return AzureCertificateHelper.executePollRequest(subscription.getServiceManagementUrl(), path, contentType, method, postData, pollPath, sslSocketFactory, MobileServiceRestManager.getManager()); } else { final PluginSettings settings = DefaultLoader.getPluginComponent().getSettings(); final String managementUri = settings.getAzureServiceManagementUri(); final UserInfo userInfo = getUserInfo(subscriptionId); return requestWithToken(userInfo, new RequestCallback<String>() { @Override public String execute() throws Throwable { String accessToken = getAccessToken(userInfo); return AzureAADHelper.executePollRequest(managementUri, path, contentType, method, postData, pollPath, accessToken, MobileServiceRestManager.getManager()); } }); } } @NotNull private <T> T requestComputeSDK(@NotNull final String subscriptionId, @NotNull final SDKRequestCallback<T, ComputeManagementClient> requestCallback) throws AzureCmdException { return requestAzureSDK(subscriptionId, requestCallback, new AzureSDKClientProvider<ComputeManagementClient>() { @NotNull @Override public ComputeManagementClient getSSLClient(@NotNull Subscription subscription) throws Throwable { return AzureSDKHelper.getComputeManagementClient(subscription.getId(), subscription.getManagementCertificate(), subscription.getServiceManagementUrl()); } @NotNull @Override public ComputeManagementClient getAADClient(@NotNull String subscriptionId, @NotNull String accessToken) throws Throwable { return AzureSDKHelper.getComputeManagementClient(subscriptionId, accessToken); } }); } @NotNull private <T> T requestStorageSDK(@NotNull final String subscriptionId, @NotNull final SDKRequestCallback<T, StorageManagementClient> requestCallback) throws AzureCmdException { return requestAzureSDK(subscriptionId, requestCallback, new AzureSDKClientProvider<StorageManagementClient>() { @NotNull @Override public StorageManagementClient getSSLClient(@NotNull Subscription subscription) throws Throwable { return AzureSDKHelper.getStorageManagementClient(subscription.getId(), subscription.getManagementCertificate(), subscription.getServiceManagementUrl()); } @NotNull @Override public StorageManagementClient getAADClient(@NotNull String subscriptionId, @NotNull String accessToken) throws Throwable { return AzureSDKHelper.getStorageManagementClient(subscriptionId, accessToken); } }); } @NotNull private <T> T requestNetworkSDK(@NotNull final String subscriptionId, @NotNull final SDKRequestCallback<T, NetworkManagementClient> requestCallback) throws AzureCmdException { return requestAzureSDK(subscriptionId, requestCallback, new AzureSDKClientProvider<NetworkManagementClient>() { @NotNull @Override public NetworkManagementClient getSSLClient(@NotNull Subscription subscription) throws Throwable { return AzureSDKHelper.getNetworkManagementClient(subscription.getId(), subscription.getManagementCertificate(), subscription.getServiceManagementUrl()); } @NotNull @Override public NetworkManagementClient getAADClient(@NotNull String subscriptionId, @NotNull String accessToken) throws Throwable { return AzureSDKHelper.getNetworkManagementClient(subscriptionId, accessToken); } }); } @NotNull private <T> T requestWebSiteSDK(@NotNull final String subscriptionId, @NotNull final SDKRequestCallback<T, WebSiteManagementClient> requestCallback) throws AzureCmdException { return requestAzureSDK(subscriptionId, requestCallback, new AzureSDKClientProvider<WebSiteManagementClient>() { @NotNull @Override public WebSiteManagementClient getSSLClient(@NotNull Subscription subscription) throws Throwable { return AzureSDKHelper.getWebSiteManagementClient(subscription.getId(), subscription.getManagementCertificate(), subscription.getServiceManagementUrl()); } @NotNull @Override public WebSiteManagementClient getAADClient(@NotNull String subscriptionId, @NotNull String accessToken) throws Throwable { return AzureSDKHelper.getWebSiteManagementClient(subscriptionId, accessToken); } }); } @NotNull private <T> T requestResourceManagementSDK(@NotNull final String subscriptionId, @NotNull final SDKRequestCallback<T, ResourceManagementClient> requestCallback) throws AzureCmdException { return requestAzureSDK(subscriptionId, requestCallback, new AzureSDKClientProvider<ResourceManagementClient>() { @NotNull @Override public ResourceManagementClient getAADClient(@NotNull String subscriptionId, @NotNull String accessToken) throws Throwable { return AzureSDKHelper.getResourceManagementClient(subscriptionId, accessToken); } @Override public ResourceManagementClient getSSLClient(Subscription subscription) throws Throwable { return AzureSDKHelper.getResourceManagementClient(subscription.getId(), subscription.getManagementCertificate(), subscription.getServiceManagementUrl()); } }); } @NotNull private <T> T requestManagementSDK(@NotNull final String subscriptionId, @NotNull final SDKRequestCallback<T, ManagementClient> requestCallback) throws AzureCmdException { return requestAzureSDK(subscriptionId, requestCallback, new AzureSDKClientProvider<ManagementClient>() { @NotNull @Override public ManagementClient getSSLClient(@NotNull Subscription subscription) throws Throwable { return AzureSDKHelper.getManagementClient(subscription.getId(), subscription.getManagementCertificate(), subscription.getServiceManagementUrl()); } @NotNull @Override public ManagementClient getAADClient(@NotNull String subscriptionId, @NotNull String accessToken) throws Throwable { return AzureSDKHelper.getManagementClient(subscriptionId, accessToken); } }); } @NotNull private <T, V extends Closeable> T requestAzureSDK(@NotNull final String subscriptionId, @NotNull final SDKRequestCallback<T, V> requestCallback, @NotNull final AzureSDKClientProvider<V> clientProvider) throws AzureCmdException { if (hasSSLSocketFactory(subscriptionId)) { try { Subscription subscription = getSubscription(subscriptionId); V client = clientProvider.getSSLClient(subscription); try { return requestCallback.execute(client); } finally { client.close(); } } catch (Throwable t) { if (t instanceof AzureCmdException) { throw (AzureCmdException) t; } else if (t instanceof ExecutionException) { throw new AzureCmdException(t.getCause().getMessage(), t.getCause()); } throw new AzureCmdException(t.getMessage(), t); } } else if (hasAccessToken()) { V client = null; try { client = clientProvider.getAADClient(subscriptionId, accessToken); return requestCallback.execute(client); } catch (Throwable throwable) { throw new AzureCmdException(throwable.getMessage(), throwable); } finally { try { if (client != null) { client.close(); } } catch (IOException e) { throw new AzureCmdException(e.getMessage(), e); } } } else { final UserInfo userInfo = getUserInfo(subscriptionId); PluginSettings settings = DefaultLoader.getPluginComponent().getSettings(); com.microsoft.tooling.msservices.helpers.auth.RequestCallback<T> aadRequestCB = new com.microsoft.tooling.msservices.helpers.auth.RequestCallback<T>() { @NotNull @Override public T execute(@NotNull String accessToken) throws Throwable { if (!hasAccessToken(userInfo) || !accessToken.equals(getAccessToken(userInfo))) { ReentrantReadWriteLock userLock = getUserLock(userInfo, true); userLock.writeLock().lock(); try { if (!hasAccessToken(userInfo) || !accessToken.equals(getAccessToken(userInfo))) { setAccessToken(userInfo, accessToken); } } finally { userLock.writeLock().unlock(); } } V client = clientProvider.getAADClient(subscriptionId, accessToken); try { return requestCallback.execute(client); } finally { client.close(); } } }; return aadManager.request(userInfo, settings.getAzureServiceManagementUri(), "Sign in to your Azure account", aadRequestCB); } } @NotNull private <T> T requestWithToken(@NotNull final UserInfo userInfo, @NotNull final RequestCallback<T> requestCallback) throws AzureCmdException { PluginSettings settings = DefaultLoader.getPluginComponent().getSettings(); com.microsoft.tooling.msservices.helpers.auth.RequestCallback<T> aadRequestCB = new com.microsoft.tooling.msservices.helpers.auth.RequestCallback<T>() { @NotNull @Override public T execute(@NotNull String accessToken) throws Throwable { if (!hasAccessToken(userInfo) || !accessToken.equals(getAccessToken(userInfo))) { ReentrantReadWriteLock userLock = getUserLock(userInfo, true); userLock.writeLock().lock(); try { if (!hasAccessToken(userInfo) || !accessToken.equals(getAccessToken(userInfo))) { setAccessToken(userInfo, accessToken); } } finally { userLock.writeLock().unlock(); } } return requestCallback.execute(); } }; return aadManager.request(userInfo, settings.getAzureServiceManagementUri(), "Sign in to your Azure account", aadRequestCB); } @NotNull private static String readFile(@NotNull String filePath) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(filePath))); try { return CharStreams.toString(in); } finally { in.close(); } } @NotNull private static String getAbsolutePath(@NotNull String dir) { return "/" + dir.trim().replace('\\', '/').replaceAll("^/+", "").replaceAll("/+$", ""); } }