Java tutorial
/** * Copyright 2014 Microsoft Open Technologies Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.microsoftopentechnologies.intellij.helpers.azure; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.gson.Gson; import com.intellij.ide.util.PropertiesComponent; import com.microsoftopentechnologies.intellij.components.MSOpenTechToolsApplication; import com.microsoftopentechnologies.intellij.helpers.CustomJsonSlurper; import com.microsoftopentechnologies.intellij.helpers.NoSubscriptionException; import com.microsoftopentechnologies.intellij.helpers.StringHelper; import com.microsoftopentechnologies.intellij.helpers.XmlHelper; import com.microsoftopentechnologies.intellij.helpers.aadauth.AuthenticationResult; import com.microsoftopentechnologies.intellij.model.*; import org.apache.commons.lang.StringUtils; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import sun.misc.BASE64Encoder; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import java.io.*; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.ExecutionException; import java.util.concurrent.locks.ReentrantLock; public class AzureRestAPIManager implements AzureManager { // singleton API manager instance private static AzureRestAPIManager apiManager = null; // This is the authentication token. // TODO: Should we store this encrypted in memory? // TODO: Implement offline encrypted caching so that user doesn't have to re-authenticate every time they run. private AuthenticationResult authenticationToken; private ReentrantLock authenticationTokenLock = new ReentrantLock(); // list of azure subscriptions private ArrayList<Subscription> subscriptions; private ReentrantLock subscriptionsLock = new ReentrantLock(); // cache of authentication tokens by azure subscription ID private Map<String, AuthenticationResult> authenticationTokenSubscriptionMap = new HashMap<String, AuthenticationResult>(); private ReentrantLock authenticationTokenSubscriptionMapLock = new ReentrantLock(); private AzureRestAPIManager() { } public static AzureManager getManager() { if (apiManager == null) { apiManager = new AzureRestAPIManager(); } return apiManager; } @Override public AzureAuthenticationMode getAuthenticationMode() { return AzureAuthenticationMode.valueOf(PropertiesComponent.getInstance().getValue( MSOpenTechToolsApplication.AppSettingsNames.AZURE_AUTHENTICATION_MODE, AzureAuthenticationMode.Unknown.toString())); } @Override public void setAuthenticationMode(AzureAuthenticationMode azureAuthenticationMode) { PropertiesComponent.getInstance().setValue( MSOpenTechToolsApplication.AppSettingsNames.AZURE_AUTHENTICATION_MODE, azureAuthenticationMode.toString()); } public AuthenticationResult getAuthenticationTokenForSubscription(String subscriptionId) { // build key for the properties cache String key = MSOpenTechToolsApplication.AppSettingsNames.AZURE_AUTHENTICATION_TOKEN + "_" + subscriptionId; // check if the token is already available in our cache if (authenticationTokenSubscriptionMap.containsKey(key)) { return authenticationTokenSubscriptionMap.get(key); } String json = PropertiesComponent.getInstance().getValue(key); if (!StringHelper.isNullOrWhiteSpace(json)) { Gson gson = new Gson(); AuthenticationResult token = gson.fromJson(json, AuthenticationResult.class); // save the token to the cache authenticationTokenSubscriptionMapLock.lock(); try { authenticationTokenSubscriptionMap.put(key, token); } finally { authenticationTokenSubscriptionMapLock.unlock(); } } return authenticationTokenSubscriptionMap.get(key); } public void setAuthenticationTokenForSubscription(String subscriptionId, AuthenticationResult authenticationToken) { // build key for the properties cache String key = MSOpenTechToolsApplication.AppSettingsNames.AZURE_AUTHENTICATION_TOKEN + "_" + subscriptionId; authenticationTokenSubscriptionMapLock.lock(); try { // update the token in the cache if (authenticationToken == null) { if (authenticationTokenSubscriptionMap.containsKey(key)) { authenticationTokenSubscriptionMap.remove(key); } } else { authenticationTokenSubscriptionMap.put(key, authenticationToken); } // save the token in persistent storage String json = ""; if (authenticationToken != null) { Gson gson = new Gson(); json = gson.toJson(authenticationToken, AuthenticationResult.class); } PropertiesComponent.getInstance().setValue(key, json); } finally { authenticationTokenSubscriptionMapLock.unlock(); } } @Override public AuthenticationResult getAuthenticationToken() { if (authenticationToken == null) { String json = PropertiesComponent.getInstance() .getValue(MSOpenTechToolsApplication.AppSettingsNames.AZURE_AUTHENTICATION_TOKEN); if (!StringHelper.isNullOrWhiteSpace(json)) { Gson gson = new Gson(); authenticationTokenLock.lock(); try { authenticationToken = gson.fromJson(json, AuthenticationResult.class); } finally { authenticationTokenLock.unlock(); } } } return authenticationToken; } @Override public void setAuthenticationToken(AuthenticationResult authenticationToken) { authenticationTokenLock.lock(); try { this.authenticationToken = authenticationToken; String json = ""; if (this.authenticationToken != null) { Gson gson = new Gson(); json = gson.toJson(this.authenticationToken, AuthenticationResult.class); } PropertiesComponent.getInstance() .setValue(MSOpenTechToolsApplication.AppSettingsNames.AZURE_AUTHENTICATION_TOKEN, json); } finally { authenticationTokenLock.unlock(); } } @Override public void clearSubscriptions() throws AzureCmdException { PropertiesComponent.getInstance().unsetValue(MSOpenTechToolsApplication.AppSettingsNames.SUBSCRIPTION_FILE); subscriptionsLock.lock(); try { if (subscriptions != null) { subscriptions.clear(); subscriptions = null; } } finally { subscriptionsLock.unlock(); } } @Override public void clearAuthenticationTokens() { if (subscriptions != null) { for (Subscription subscription : subscriptions) { setAuthenticationTokenForSubscription(subscription.getId().toString(), null); } } setAuthenticationToken(null); } @Override public ArrayList<Subscription> getSubscriptionList() throws AzureCmdException { try { AzureAuthenticationMode mode = getAuthenticationMode(); ArrayList<Subscription> fullList = null; if (mode == AzureAuthenticationMode.SubscriptionSettings) { fullList = getSubscriptionListFromCert(); } else if (mode == AzureAuthenticationMode.ActiveDirectory) { fullList = getSubscriptionListFromToken(); } if (fullList != null) { ArrayList<Subscription> ret = new ArrayList<Subscription>(); for (Subscription subscription : fullList) { if (subscription.isSelected()) ret.add(subscription); } return ret; } return null; } catch (Exception e) { throw new AzureCmdException("Error getting subscription list", e); } } @Override public ArrayList<Subscription> getFullSubscriptionList() throws AzureCmdException { try { AzureAuthenticationMode mode = getAuthenticationMode(); if (mode == AzureAuthenticationMode.SubscriptionSettings) { return getSubscriptionListFromCert(); } else if (mode == AzureAuthenticationMode.ActiveDirectory) { return getSubscriptionListFromToken(); } return null; } catch (Exception e) { throw new AzureCmdException("Error getting subscription list", e); } } public void setSelectedSubscriptions(List<UUID> selectedList) throws AzureCmdException { try { AzureAuthenticationMode mode = getAuthenticationMode(); if (mode == AzureAuthenticationMode.SubscriptionSettings) { String subscriptionFile = PropertiesComponent.getInstance() .getValue(MSOpenTechToolsApplication.AppSettingsNames.SUBSCRIPTION_FILE, ""); NodeList subscriptionList = (NodeList) XmlHelper.getXMLValue(subscriptionFile, "//Subscription", XPathConstants.NODESET); for (int i = 0; i < subscriptionList.getLength(); i++) { UUID id = UUID.fromString(XmlHelper.getAttributeValue(subscriptionList.item(i), "Id")); Node node = subscriptionList.item(i).getAttributes().getNamedItem("Selected"); if (node == null) { node = subscriptionList.item(i).getOwnerDocument().createAttribute("Selected"); } node.setNodeValue(selectedList.contains(id) ? "true" : "false"); subscriptionList.item(i).getAttributes().setNamedItem(node); } if (subscriptionList.getLength() > 0) { String savedXml = XmlHelper.saveXmlToStreamWriter(subscriptionList.item(0).getOwnerDocument()); PropertiesComponent.getInstance() .setValue(MSOpenTechToolsApplication.AppSettingsNames.SUBSCRIPTION_FILE, savedXml); } } else if (mode == AzureAuthenticationMode.ActiveDirectory) { for (Subscription subscription : subscriptions) { subscription.setSelected(selectedList.contains(subscription.getId())); } ArrayList<String> selectedIds = new ArrayList<String>(); for (UUID uuid : selectedList) { selectedIds.add(uuid.toString()); } PropertiesComponent.getInstance().setValue( MSOpenTechToolsApplication.AppSettingsNames.SELECTED_SUBSCRIPTIONS, StringUtils.join(selectedIds, ",")); } } catch (Exception e) { throw new AzureCmdException("Error getting subscription list", e); } } public ArrayList<Subscription> getSubscriptionListFromCert() throws SAXException, ParserConfigurationException, XPathExpressionException, IOException { String subscriptionFile = PropertiesComponent.getInstance() .getValue(MSOpenTechToolsApplication.AppSettingsNames.SUBSCRIPTION_FILE, ""); if (subscriptionFile.trim().isEmpty()) { return null; } NodeList subscriptionList = (NodeList) XmlHelper.getXMLValue(subscriptionFile, "//Subscription", XPathConstants.NODESET); ArrayList<Subscription> list = new ArrayList<Subscription>(); for (int i = 0; i < subscriptionList.getLength(); i++) { Subscription subscription = new Subscription(); subscription.setName(XmlHelper.getAttributeValue(subscriptionList.item(i), "Name")); subscription.setId(UUID.fromString(XmlHelper.getAttributeValue(subscriptionList.item(i), "Id"))); String selected = XmlHelper.getAttributeValue(subscriptionList.item(i), "Selected"); subscription.setSelected(selected == null || selected.equals("true")); list.add(subscription); } return list; } public void refreshSubscriptionListFromToken() throws IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, ExecutionException, ParserConfigurationException, InterruptedException, AzureCmdException, SAXException, NoSubscriptionException, KeyStoreException, XPathExpressionException, KeyManagementException { ArrayList<UUID> selectedIds = new ArrayList<UUID>(); String selectedSubscriptions = null; if (PropertiesComponent.getInstance() .isValueSet(MSOpenTechToolsApplication.AppSettingsNames.SELECTED_SUBSCRIPTIONS)) { selectedSubscriptions = PropertiesComponent.getInstance() .getValue(MSOpenTechToolsApplication.AppSettingsNames.SELECTED_SUBSCRIPTIONS, ""); } if (selectedSubscriptions != null && !selectedSubscriptions.isEmpty()) { for (String id : selectedSubscriptions.split(",")) { selectedIds.add(UUID.fromString(id)); } } String subscriptionXml = AzureRestAPIHelper.getRestApiCommand("subscriptions", null); PropertiesComponent.getInstance().setValue(MSOpenTechToolsApplication.AppSettingsNames.SUBSCRIPTION_FILE, subscriptionXml); NodeList subscriptionList = (NodeList) XmlHelper.getXMLValue(subscriptionXml, "//Subscription", XPathConstants.NODESET); subscriptionsLock.lock(); try { 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( UUID.fromString(XmlHelper.getChildNodeValue(subscriptionList.item(i), "SubscriptionID"))); subscription.setTenantId(XmlHelper.getChildNodeValue(subscriptionList.item(i), "AADTenantID")); subscription .setSelected(selectedSubscriptions == null || selectedIds.contains(subscription.getId())); subscriptions.add(subscription); } } finally { subscriptionsLock.unlock(); } } public ArrayList<Subscription> getSubscriptionListFromToken() throws AzureCmdException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, ExecutionException, ParserConfigurationException, InterruptedException, SAXException, NoSubscriptionException, KeyStoreException, XPathExpressionException, KeyManagementException { if (subscriptions == null) { refreshSubscriptionListFromToken(); assert subscriptions != null; } return subscriptions; } public Subscription getSubscriptionFromId(final String subscriptionId) throws SAXException, ParserConfigurationException, XPathExpressionException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, ExecutionException, InterruptedException, KeyManagementException, KeyStoreException, AzureCmdException, NoSubscriptionException { ArrayList<Subscription> subscriptions = null; AzureAuthenticationMode mode = getAuthenticationMode(); if (mode == AzureAuthenticationMode.SubscriptionSettings) { subscriptions = getSubscriptionListFromCert(); } else if (mode == AzureAuthenticationMode.ActiveDirectory) { subscriptions = getSubscriptionListFromToken(); } if (subscriptions == null) { return null; } final UUID sid = UUID.fromString(subscriptionId); return Iterables.find(subscriptions, new Predicate<Subscription>() { @Override public boolean apply(Subscription subscription) { return subscription.getId().compareTo(sid) == 0; } }); } @Override public void loadSubscriptionFile(String subscriptionFile) throws AzureCmdException { // update the auth mode and clear out the subscriptions xml setAuthenticationMode(AzureAuthenticationMode.SubscriptionSettings); apiManager.clearSubscriptions(); AzureRestAPIHelper.importSubscription(new File(subscriptionFile)); } @Override public void removeSubscription(String subscriptionId) throws AzureCmdException { try { AzureRestAPIHelper.removeSubscription(subscriptionId); } catch (Exception e) { throw new AzureCmdException("Error removing subscription", e); } } @Override public List<Service> getServiceList(UUID subscriptionId) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices", subscriptionId.toString()); String json = AzureRestAPIHelper.getRestApiCommand(path, subscriptionId.toString()); CustomJsonSlurper slurper = new CustomJsonSlurper(); List<Map<String, Object>> tempRes = (List<Map<String, Object>>) slurper.parseText(json); List<Service> res = new ArrayList<Service>(); for (Map<String, Object> item : tempRes) { Service ser = new Service(); ser.setName((String) item.get("name")); ser.setType((String) item.get("type")); ser.setState((String) item.get("state")); ser.setSelfLink((String) item.get("selflink")); ser.setAppUrl((String) item.get("applicationUrl")); ser.setAppKey((String) item.get("applicationKey")); ser.setMasterKey((String) item.get("masterKey")); ser.setWebspace((String) item.get("webspace")); ser.setRegion((String) item.get("region")); ser.setMgmtPortalLink((String) item.get("managementPortalLink")); ser.setSubcriptionId(subscriptionId); if (item.containsKey("platform") && item.get("platform").equals("dotNet")) { ser.setRuntime(Service.NET_RUNTIME); } else { ser.setRuntime(Service.NODE_RUNTIME); } for (Map<String, String> table : (List<Map<String, String>>) item.get("tables")) { Table t = new Table(); t.setName(table.get("name")); t.setSelfLink(table.get("selflink")); ser.getTables().add(t); } res.add(ser); } return res; } catch (Exception e) { throw new AzureCmdException("Error getting service list", e); } } @Override public List<String> getLocations(UUID subscriptionId) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/regions", subscriptionId.toString()); String json = AzureRestAPIHelper.getRestApiCommand(path, subscriptionId.toString()); CustomJsonSlurper slurper = new CustomJsonSlurper(); List<Map<String, String>> tempRes = (List<Map<String, String>>) slurper.parseText(json); List<String> res = new ArrayList<String>(); for (Map<String, String> item : tempRes) { res.add(item.get("region")); } return res; } catch (Exception e) { throw new AzureCmdException("Error getting region list", e); } } @Override public List<SqlDb> getSqlDb(UUID subscriptionId, SqlServer server) throws AzureCmdException { try { String path = String.format("/%s/services/sqlservers/servers/%s/databases?contentview=generic", subscriptionId.toString(), server.getName()); String xml = AzureRestAPIHelper.getRestApiCommand(path, subscriptionId.toString()); 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 (Exception e) { throw new AzureCmdException("Error getting database list", e); } } @Override public List<SqlServer> getSqlServers(UUID subscriptionId) throws AzureCmdException { try { String path = String.format("/%s/services/sqlservers/servers", subscriptionId.toString()); String xml = AzureRestAPIHelper.getRestApiCommand(path, subscriptionId.toString()); 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 (Exception e) { throw new AzureCmdException("Error getting server list", e); } } @Override public void createService(UUID subscriptionId, String region, String username, String password, String serviceName, String server, String database) throws AzureCmdException { try { String path = String.format("/%s/applications", subscriptionId.toString()); String JSONParameter; if (database == null || server == null) { String zumoServerId = UUID.randomUUID().toString().replace("-", ""); String zumoDBId = UUID.randomUUID().toString().replace("-", ""); String dbName = serviceName + "_db"; JSONParameter = "{'SchemaVersion':'2012-05.1.0','Location':'" + region + "','ExternalResources':{},'InternalResources':{'ZumoMobileService':" + "{'ProvisioningParameters':{'Name':'" + serviceName + "','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.toString() + "/services/sqlservers/servers/" + server + "'}," + "'ZumoSqlDatabase_" + zumoDBId + "':{'Name':'ZumoSqlDatabase_" + zumoDBId + "','Type':'Microsoft.WindowsAzure.SQLAzure.DataBase'," + "'URI':'https://management.core.windows.net:8443/" + subscriptionId.toString() + "/services/sqlservers/servers/" + server + "/databases/" + database + "'}}," + "'InternalResources':{'ZumoMobileService':{'ProvisioningParameters'" + ":{'Name':'" + serviceName + "','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>", serviceName + "mobileservice", serviceName, serviceName, new BASE64Encoder().encode(JSONParameter.getBytes())); AzureRestAPIHelper.postRestApiCommand(path, xmlParameter, subscriptionId.toString(), String.format("/%s/operations/", subscriptionId.toString()), false); String xml = AzureRestAPIHelper.getRestApiCommand( String.format("/%s/applications/%s", subscriptionId.toString(), serviceName + "mobileservice"), subscriptionId.toString()); NodeList statusNode = ((NodeList) XmlHelper.getXMLValue(xml, "//Application/State", XPathConstants.NODESET)); if (statusNode.getLength() > 0 && statusNode.item(0).getTextContent().equals("Healthy")) { return; } else { deleteService(subscriptionId, serviceName); 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; } else { throw new AzureCmdException("Error creating service", t); } } } private void deleteService(UUID subscriptionId, String serviceName) { String mspath = String.format("/%s/services/mobileservices/mobileservices/%s?deletedata=true", subscriptionId.toString(), serviceName); try { AzureRestAPIHelper.deleteRestApiCommand(mspath, subscriptionId.toString(), String.format("/%s/operations/", subscriptionId.toString()), true); } catch (Throwable t) { } String appPath = String.format("/%s/applications/%smobileservice", subscriptionId.toString(), serviceName); try { AzureRestAPIHelper.deleteRestApiCommand(appPath, subscriptionId.toString(), String.format("/%s/operations/", subscriptionId.toString()), false); } catch (Throwable t) { } } @Override public List<Table> getTableList(UUID subscriptionId, String serviceName) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/tables", subscriptionId.toString(), serviceName); String json = AzureRestAPIHelper.getRestApiCommand(path, subscriptionId.toString()); CustomJsonSlurper slurper = new CustomJsonSlurper(); List<Map<String, String>> tempRes = (List<Map<String, String>>) slurper.parseText(json); List<Table> res = new ArrayList<Table>(); for (Map<String, String> item : tempRes) { Table t = new Table(); t.setName(item.get("name")); t.setSelfLink(item.get("selflink")); res.add(t); } return res; } catch (Exception e) { throw new AzureCmdException("Error getting table list", e); } } @Override public void createTable(UUID subscriptionId, String serviceName, String tableName, TablePermissions permissions) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/tables", subscriptionId.toString(), serviceName); 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\"}"; AzureRestAPIHelper.postRestApiCommand(path, postData, subscriptionId.toString(), null, true); } catch (Exception e) { throw new AzureCmdException("Error creating table", e); } } @Override public void updateTable(UUID subscriptionId, String serviceName, String tableName, TablePermissions permissions) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/tables/%s/permissions", subscriptionId.toString(), serviceName, tableName); String postData = "{\"insert\":\"" + PermissionItem.getPermitionString(permissions.getInsert()) + "\",\"read\":\"" + PermissionItem.getPermitionString(permissions.getRead()) + "\",\"update\":\"" + PermissionItem.getPermitionString(permissions.getUpdate()) + "\",\"delete\":\"" + PermissionItem.getPermitionString(permissions.getDelete()) + "\"}"; AzureRestAPIHelper.putRestApiCommand(path, postData, subscriptionId.toString(), null, true); } catch (Exception e) { throw new AzureCmdException("Error updating table", e); } } @Override public Table showTableDetails(UUID subscriptionId, String serviceName, String tableName) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/tables/%s", subscriptionId.toString(), serviceName, tableName); String json = AzureRestAPIHelper.getRestApiCommand(path, subscriptionId.toString()); CustomJsonSlurper slurper = new CustomJsonSlurper(); Table t = new Table(); Map<String, Object> tableData = (Map<String, Object>) slurper.parseText(json); t.setName(tableData.get("name").toString()); t.setSelfLink(tableData.get("selflink").toString()); Map<String, String> per = (Map<String, String>) slurper.parseText( AzureRestAPIHelper.getRestApiCommand(path + "/permissions", subscriptionId.toString())); TablePermissions tablePermissions = new TablePermissions(); tablePermissions.setInsert(PermissionItem.getPermitionType(per.get("insert"))); tablePermissions.setUpdate(PermissionItem.getPermitionType(per.get("update"))); tablePermissions.setRead(PermissionItem.getPermitionType(per.get("read"))); tablePermissions.setDelete(PermissionItem.getPermitionType(per.get("delete"))); t.setTablePermissions(tablePermissions); for (Map<String, Object> column : (List<Map<String, Object>>) slurper.parseText( AzureRestAPIHelper.getRestApiCommand(path + "/columns", subscriptionId.toString()))) { Column c = new Column(); c.setName(column.get("name").toString()); c.setType(column.get("type").toString()); c.setSelfLink(column.get("selflink").toString()); c.setIndexed((Boolean) column.get("indexed")); c.setZumoIndex((Boolean) column.get("zumoIndex")); t.getColumns().add(c); } for (Map<String, Object> script : (List<Map<String, Object>>) slurper.parseText( AzureRestAPIHelper.getRestApiCommand(path + "/scripts", subscriptionId.toString()))) { Script s = new Script(); s.setOperation(script.get("operation").toString()); s.setBytes((Integer) script.get("sizeBytes")); s.setSelfLink(script.get("selflink").toString()); s.setName(String.format("%s.%s", tableData.get("name"), script.get("operation").toString())); t.getScripts().add(s); } return t; } catch (Exception e) { throw new AzureCmdException("Error getting table data", e); } } @Override public void downloadTableScript(UUID subscriptionId, String serviceName, String scriptName, 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.toString(), serviceName, tableName, operation); String script = AzureRestAPIHelper.getRestApiCommand(path, subscriptionId.toString()); Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(downloadPath), "utf-8")); writer.write(script); writer.flush(); writer.close(); } catch (Exception e) { //On error, create script for template } } @Override public void uploadTableScript(UUID subscriptionId, String serviceName, String scriptName, 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.toString(), serviceName, tableName, operation); AzureRestAPIHelper.uploadScript(path, filePath, subscriptionId.toString()); } catch (Exception e) { throw new AzureCmdException("Error upload script", e); } } @Override public List<CustomAPI> getAPIList(UUID subscriptionId, String serviceName) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/apis", subscriptionId.toString(), serviceName); String json = AzureRestAPIHelper.getRestApiCommand(path, subscriptionId.toString()); CustomJsonSlurper slurper = new CustomJsonSlurper(); List<Map<String, String>> tempRes = (List<Map<String, String>>) slurper.parseText(json); List<CustomAPI> res = new ArrayList<CustomAPI>(); for (Map<String, String> item : tempRes) { CustomAPI c = new CustomAPI(); c.setName(item.get("name")); CustomAPIPermissions permissions = new CustomAPIPermissions(); permissions.setPutPermission(PermissionItem.getPermitionType(item.get("put"))); permissions.setPostPermission(PermissionItem.getPermitionType(item.get("post"))); permissions.setGetPermission(PermissionItem.getPermitionType(item.get("get"))); permissions.setDeletePermission(PermissionItem.getPermitionType(item.get("delete"))); permissions.setPatchPermission(PermissionItem.getPermitionType(item.get("patch"))); c.setCustomAPIPermissions(permissions); res.add(c); } return res; } catch (Exception e) { throw new AzureCmdException("Error getting API list", e); } } @Override public void downloadAPIScript(UUID subscriptionId, String serviceName, String scriptName, String downloadPath) throws AzureCmdException { try { String apiName = scriptName.split("\\.")[0]; String path = String.format("/%s/services/mobileservices/mobileservices/%s/apis/%s/script", subscriptionId.toString(), serviceName, apiName); String script = AzureRestAPIHelper.getRestApiCommand(path, subscriptionId.toString()); Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(downloadPath), "utf-8")); writer.write(script); writer.flush(); writer.close(); } catch (Exception e) { throw new AzureCmdException("Error getting API list", e); } } @Override public void uploadAPIScript(UUID subscriptionId, String serviceName, String scriptName, String filePath) throws AzureCmdException { try { String apiName = scriptName.split("\\.")[0]; String path = String.format("/%s/services/mobileservices/mobileservices/%s/apis/%s/script", subscriptionId.toString(), serviceName, apiName); AzureRestAPIHelper.uploadScript(path, filePath, subscriptionId.toString()); } catch (Exception e) { throw new AzureCmdException("Error upload script", e); } } @Override public void createCustomAPI(UUID subscriptionId, String serviceName, String tableName, CustomAPIPermissions permissions) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/apis", subscriptionId.toString(), serviceName); String postData = "{\"get\":\"" + permissions.getGetPermission() + "\",\"put\":\"" + permissions.getPutPermission() + "\",\"post\":\"" + permissions.getPostPermission() + "\",\"patch\":\"" + permissions.getPatchPermission() + "\",\"delete\":\"" + permissions.getDeletePermission() + "\",\"name\":\"" + tableName + "\"}"; AzureRestAPIHelper.postRestApiCommand(path, postData, subscriptionId.toString(), null, true); } catch (Exception e) { throw new AzureCmdException("Error creating API", e); } } @Override public void updateCustomAPI(UUID subscriptionId, String serviceName, String tableName, CustomAPIPermissions permissions) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/apis/%s", subscriptionId.toString(), serviceName, tableName); String postData = "{\"get\":\"" + permissions.getGetPermission() + "\",\"put\":\"" + permissions.getPutPermission() + "\",\"post\":\"" + permissions.getPostPermission() + "\",\"patch\":\"" + permissions.getPatchPermission() + "\",\"delete\":\"" + permissions.getDeletePermission() + "\"}"; AzureRestAPIHelper.putRestApiCommand(path, postData, subscriptionId.toString(), null, true); } catch (Exception e) { throw new AzureCmdException("Error updating API", e); } } @Override public List<Job> listJobs(UUID subscriptionId, String serviceName) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/scheduler/jobs", subscriptionId.toString(), serviceName); String json = AzureRestAPIHelper.getRestApiCommand(path, subscriptionId.toString()); CustomJsonSlurper slurper = new CustomJsonSlurper(); List<Map<String, Object>> tempRes = (List<Map<String, Object>>) slurper.parseText(json); List<Job> res = new ArrayList<Job>(); for (Map<String, Object> item : tempRes) { Job j = new Job(); j.setAppName(item.get("appName").toString()); j.setName(item.get("name").toString()); j.setEnabled(item.get("status").equals("enabled")); j.setId(UUID.fromString(item.get("id").toString())); if (item.get("intervalPeriod") != null) { j.setIntervalPeriod((Integer) item.get("intervalPeriod")); j.setIntervalUnit(item.get("intervalUnit").toString()); } res.add(j); } return res; } catch (Exception e) { throw new AzureCmdException("Error getting job list", e); } } @Override public void createJob(UUID subscriptionId, String serviceName, String jobName, int interval, String intervalUnit, String startDate) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/scheduler/jobs", subscriptionId.toString(), serviceName); String postData = "{\"name\":\"" + jobName + "\"" + (intervalUnit .equals("none") ? "" : (",\"intervalUnit\":\"" + intervalUnit + "\",\"intervalPeriod\":" + String.valueOf(interval) + ",\"startTime\":\"" + startDate + "\"")) + "}"; AzureRestAPIHelper.postRestApiCommand(path, postData, subscriptionId.toString(), null, true); } catch (Exception e) { throw new AzureCmdException("Error creating jobs", e); } } @Override public void updateJob(UUID subscriptionId, String serviceName, String jobName, int interval, String intervalUnit, String startDate, boolean enabled) throws AzureCmdException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/scheduler/jobs/%s", subscriptionId.toString(), serviceName, 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\"}"; } AzureRestAPIHelper.putRestApiCommand(path, postData, subscriptionId.toString(), null, true); } catch (Exception e) { throw new AzureCmdException("Error updating job", e); } } @Override public void downloadJobScript(UUID subscriptionId, String serviceName, String scriptName, String downloadPath) throws AzureCmdException { try { String jobName = scriptName.split("\\.")[0]; String path = String.format("/%s/services/mobileservices/mobileservices/%s/scheduler/jobs/%s/script", subscriptionId.toString(), serviceName, jobName); String script = AzureRestAPIHelper.getRestApiCommand(path, subscriptionId.toString()); Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(downloadPath), "utf-8")); writer.write(script); writer.flush(); writer.close(); } catch (Exception e) { e.printStackTrace(); //On error, create script for template } } @Override public void uploadJobScript(UUID subscriptionId, String serviceName, String scriptName, String filePath) throws AzureCmdException { try { String jobName = scriptName.split("\\.")[0]; String path = String.format("/%s/services/mobileservices/mobileservices/%s/scheduler/jobs/%s/script", subscriptionId.toString(), serviceName, jobName); AzureRestAPIHelper.uploadScript(path, filePath, subscriptionId.toString()); } catch (Exception e) { throw new AzureCmdException("Error upload script", e); } } @Override public List<LogEntry> listLog(UUID subscriptionId, String serviceName, String runtime) throws AzureCmdException, ParseException { try { String path = String.format("/%s/services/mobileservices/mobileservices/%s/logs?$top=10", subscriptionId.toString(), serviceName); String json = AzureRestAPIHelper.getRestApiCommand(path, subscriptionId.toString()); CustomJsonSlurper slurper = new CustomJsonSlurper(); Map<String, Object> results = (Map<String, Object>) slurper.parseText(json); List<Map<String, String>> tempRes = (List<Map<String, String>>) results.get("results"); List<LogEntry> res = new ArrayList<LogEntry>(); for (Map<String, String> item : tempRes) { LogEntry logEntry = new LogEntry(); logEntry.setMessage(item.get("message")); logEntry.setSource(item.get("source")); logEntry.setType(item.get("type")); SimpleDateFormat ISO8601DATEFORMAT; if (Service.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.get("timeCreated"))); res.add(logEntry); } return res; } catch (Exception e) { throw new AzureCmdException("Error getting log", e); } } }