PageRenderTime 70ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/backend/src/main/java/com/gooddata/integration/rest/GdcRESTApiWrapper.java

https://github.com/chrbayer84/GoodData-CL
Java | 3612 lines | 2682 code | 258 blank | 672 comment | 638 complexity | bb3f18c8650bfde5a04dfb923f1c73d6 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /*
  2. * Copyright (c) 2009, GoodData Corporation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without modification, are permitted provided
  5. * that the following conditions are met:
  6. *
  7. * * Redistributions of source code must retain the above copyright notice, this list of conditions and
  8. * the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
  10. * and the following disclaimer in the documentation and/or other materials provided with the distribution.
  11. * * Neither the name of the GoodData Corporation nor the names of its contributors may be used to endorse
  12. * or promote products derived from this software without specific prior written permission.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
  15. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  16. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  17. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  19. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  20. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  21. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22. */
  23. package com.gooddata.integration.rest;
  24. import com.gooddata.Constants;
  25. import com.gooddata.exception.*;
  26. import com.gooddata.integration.model.Column;
  27. import com.gooddata.integration.model.Project;
  28. import com.gooddata.integration.model.SLI;
  29. import com.gooddata.integration.rest.configuration.NamePasswordConfiguration;
  30. import com.gooddata.util.FileUtil;
  31. import com.gooddata.util.NetUtil;
  32. import net.sf.json.JSON;
  33. import net.sf.json.JSONArray;
  34. import net.sf.json.JSONObject;
  35. import org.apache.commons.httpclient.HttpClient;
  36. import org.apache.commons.httpclient.HttpException;
  37. import org.apache.commons.httpclient.HttpMethod;
  38. import org.apache.commons.httpclient.HttpStatus;
  39. import org.apache.commons.httpclient.cookie.CookiePolicy;
  40. import org.apache.commons.httpclient.methods.DeleteMethod;
  41. import org.apache.commons.httpclient.methods.GetMethod;
  42. import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
  43. import org.apache.commons.httpclient.methods.PostMethod;
  44. import org.apache.commons.httpclient.methods.PutMethod;
  45. import org.apache.commons.lang.StringUtils;
  46. import org.apache.log4j.Logger;
  47. import java.io.ByteArrayInputStream;
  48. import java.io.IOException;
  49. import java.io.UnsupportedEncodingException;
  50. import java.net.MalformedURLException;
  51. import java.net.URL;
  52. import java.nio.charset.Charset;
  53. import java.util.*;
  54. import java.util.regex.Matcher;
  55. import java.util.regex.Pattern;
  56. /**
  57. * The GoodData REST API Java wrapper.
  58. *
  59. * @author Zdenek Svoboda <zd@gooddata.org>
  60. * @version 1.0
  61. */
  62. public class GdcRESTApiWrapper {
  63. private static Logger l = Logger.getLogger(GdcRESTApiWrapper.class);
  64. /**
  65. * GDC URIs
  66. */
  67. private static final String PLATFORM_URI = "/gdc/";
  68. private static final String MD_URI = "/gdc/md/";
  69. private static final String LOGIN_URI = "/gdc/account/login";
  70. private static final String DOMAIN_URI = "/gdc/account/domains";
  71. private static final String DOMAIN_USERS_SUFFIX = "/users";
  72. private static final String PROJECT_USERS_SUFFIX = "/users";
  73. private static final String PROJECT_ROLES_SUFFIX = "/roles";
  74. private static final String TOKEN_URI = "/gdc/account/token";
  75. private static final String DATA_INTERFACES_URI = "/ldm/singleloadinterface";
  76. private static final String PROJECTS_URI = "/gdc/projects";
  77. private static final String PULL_URI = "/etl/pull";
  78. private static final String IDENTIFIER_URI = "/identifiers";
  79. private static final String SLI_DESCRIPTOR_URI = "/descriptor";
  80. public static final String MAQL_EXEC_URI = "/ldm/manage";
  81. public static final String MAQL_ASYNC_EXEC_URI = "/ldm/manage2";
  82. public static final String DML_EXEC_URI = "/dml/manage";
  83. public static final String PROJECT_EXPORT_URI = "/maintenance/export";
  84. public static final String PROJECT_IMPORT_URI = "/maintenance/import";
  85. public static final String PROJECT_PARTIAL_EXPORT_URI = "/maintenance/partialmdexport";
  86. public static final String PROJECT_PARTIAL_IMPORT_URI = "/maintenance/partialmdimport";
  87. public static final String REPORT_QUERY = "/query/reports";
  88. public static final String ATTR_QUERY = "/query/attributes";
  89. public static final String EXECUTOR = "/gdc/xtab2/executor3";
  90. public static final String EXPORT_EXECUTOR = "/gdc/exporter/executor";
  91. public static final String INVITATION_URI = "/invitations";
  92. public static final String ETL_MODE_URI = "/etl/mode";
  93. public static final String OBJ_URI = "/obj";
  94. public static final String ROLES_URI = "/roles";
  95. public static final String USERS_URI = "/users";
  96. public static final String ETL_MODE_DLI = "DLI";
  97. public static final String ETL_MODE_VOID = "VOID";
  98. public static final String LINKS_UPLOADS_KEY = "uploads";
  99. public static final String DLI_MANIFEST_FILENAME = "upload_info.json";
  100. public static final String QUERY_PROJECTDASHBOARDS = "projectdashboards";
  101. public static final String QUERY_FOLDERS = "folders";
  102. public static final String QUERY_DATASETS = "datasets";
  103. public static final String QUERY_DIMENSIONS = "dimensions";
  104. public static final String QUERY_PREFIX = "/query/";
  105. protected HttpClient client;
  106. protected NamePasswordConfiguration config;
  107. private JSONObject userLogin = null;
  108. private JSONObject profile;
  109. private static HashMap<String, String> ROLES = new HashMap<String, String>();
  110. private static final Pattern NEWLINE_SEPARATOR_PARSER = Pattern.compile( "\n" );
  111. /* TODO This is fragile and may not work for all projects and/or future versions.
  112. * Use /gdc/projects/{projectId}/roles to retrieve roles for a particular project.
  113. */
  114. static {
  115. ROLES.put("ADMIN", "adminRole");
  116. ROLES.put("EDITOR", "editorRole");
  117. ROLES.put("DASHBOARD ONLY", "dashboardOnlyRole");
  118. ROLES.put("UNVERIFIED ADMIN", "unverifiedAdminRole");
  119. ROLES.put("READONLY", "readOnlyUserRole");
  120. }
  121. /**
  122. * Constructs the GoodData REST API Java wrapper
  123. *
  124. * @param config NamePasswordConfiguration object with the GDC name and password configuration
  125. */
  126. public GdcRESTApiWrapper(NamePasswordConfiguration config) {
  127. this.config = config;
  128. client = new HttpClient();
  129. NetUtil.configureHttpProxy(client);
  130. }
  131. /**
  132. * GDC login - obtain GDC SSToken
  133. *
  134. * @throws HttpMethodException
  135. */
  136. public void login() throws HttpMethodException {
  137. //logout();
  138. l.debug("Logging into GoodData.");
  139. JSONObject loginStructure = getLoginStructure();
  140. PostMethod loginPost = createPostMethod(getServerUrl() + LOGIN_URI);
  141. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(loginStructure.toString().getBytes()));
  142. loginPost.setRequestEntity(request);
  143. try {
  144. String resp = executeMethodOk(loginPost, false); // do not re-login on SC_UNAUTHORIZED
  145. // enabling this prevents the following message:
  146. // WARN org.apache.commons.httpclient.HttpMethodDirector -
  147. // Unable to respond to any of these challenges:
  148. // {gooddata=GoodData realm="GoodData API" cookie=GDCAuthTT}
  149. // appearing always after those:
  150. // DEBUG com.gooddata.integration.rest.GdcRESTApiWrapper -
  151. // Logging into GoodData.
  152. // DEBUG com.gooddata.integration.rest.GdcRESTApiWrapper -
  153. // Successfully logged into GoodData.
  154. setTokenCookie();
  155. l.debug("Successfully logged into GoodData.");
  156. JSONObject rsp = JSONObject.fromObject(resp);
  157. userLogin = rsp.getJSONObject("userLogin");
  158. String profileUri = userLogin.getString("profile");
  159. if (profileUri != null && profileUri.length() > 0) {
  160. GetMethod gm = createGetMethod(getServerUrl() + profileUri);
  161. try {
  162. resp = executeMethodOk(gm);
  163. this.profile = JSONObject.fromObject(resp);
  164. }
  165. finally {
  166. gm.releaseConnection();
  167. }
  168. } else {
  169. l.debug("Empty account profile.");
  170. throw new GdcRestApiException("Empty account profile.");
  171. }
  172. } finally {
  173. loginPost.releaseConnection();
  174. }
  175. }
  176. /**
  177. * Creates a new login JSON structure
  178. *
  179. * @return the login JSON structure
  180. */
  181. private JSONObject getLoginStructure() {
  182. JSONObject credentialsStructure = new JSONObject();
  183. credentialsStructure.put("login", config.getUsername());
  184. credentialsStructure.put("password", config.getPassword());
  185. credentialsStructure.put("remember", 1);
  186. JSONObject loginStructure = new JSONObject();
  187. loginStructure.put("postUserLogin", credentialsStructure);
  188. return loginStructure;
  189. }
  190. /**
  191. * Sets the SS token
  192. *
  193. * @throws HttpMethodException
  194. */
  195. private void setTokenCookie() throws HttpMethodException {
  196. HttpMethod secutityTokenGet = createGetMethod(getServerUrl() + TOKEN_URI);
  197. try {
  198. executeMethodOk(secutityTokenGet);
  199. } finally {
  200. secutityTokenGet.releaseConnection();
  201. }
  202. }
  203. /**
  204. * GDC logout - remove active session, if any exists
  205. *
  206. * @throws HttpMethodException
  207. */
  208. public void logout() throws HttpMethodException {
  209. if (userLogin == null)
  210. return;
  211. l.debug("Logging out.");
  212. DeleteMethod logoutDelete = createDeleteMethod(getServerUrl() + userLogin.getString("state"));
  213. try {
  214. String resp = executeMethodOk(logoutDelete, false); // do not re-login on SC_UNAUTHORIZED
  215. userLogin = null;
  216. profile = null;
  217. l.debug("Successfully logged out.");
  218. } finally {
  219. logoutDelete.releaseConnection();
  220. }
  221. this.client = new HttpClient();
  222. NetUtil.configureHttpProxy( client );
  223. }
  224. /**
  225. * Retrieves the project info by the project's ID
  226. *
  227. * @param id the project id
  228. * @return the GoodDataProjectInfo populated with the project's information
  229. * @throws HttpMethodException
  230. * @throws GdcProjectAccessException
  231. */
  232. public Project getProjectById(String id) throws HttpMethodException, GdcProjectAccessException {
  233. l.debug("Getting project by id=" + id);
  234. HttpMethod req = createGetMethod(getServerUrl() + PROJECTS_URI + "/" + id);
  235. try {
  236. String resp = executeMethodOk(req);
  237. JSONObject parsedResp = JSONObject.fromObject(resp);
  238. if(parsedResp != null && !parsedResp.isEmpty() && !parsedResp.isNullObject()) {
  239. JSONObject project = parsedResp.getJSONObject("project");
  240. if(project != null && !project.isEmpty() && !project.isNullObject()) {
  241. JSONObject meta = project.getJSONObject("meta");
  242. String title = meta.getString("title");
  243. if(title != null && title.length() > 0)
  244. return new Project(MD_URI + "/" + id, id, title);
  245. else
  246. throw new InvalidArgumentException("getProjectById: The project structure doesn't contain the title key.");
  247. }
  248. else {
  249. throw new InvalidArgumentException("getProjectById: The project structure doesn't contain the project key.");
  250. }
  251. } else {
  252. throw new InvalidArgumentException("getProjectById: Invalid response.");
  253. }
  254. } catch (HttpMethodException e) {
  255. l.debug("The project id=" + id + " doesn't exists.");
  256. throw new GdcProjectAccessException("The project id=" + id + " doesn't exists.");
  257. } finally {
  258. req.releaseConnection();
  259. }
  260. }
  261. /**
  262. * Returns the global platform links
  263. *
  264. * @return accessible platform links
  265. * @throws com.gooddata.exception.HttpMethodException
  266. *
  267. */
  268. @SuppressWarnings("unchecked")
  269. private Iterator<JSONObject> getPlatformLinks() throws HttpMethodException {
  270. l.debug("Getting project links.");
  271. HttpMethod req = createGetMethod(getServerUrl() + PLATFORM_URI);
  272. try {
  273. String resp = executeMethodOk(req);
  274. JSONObject parsedResp = JSONObject.fromObject(resp);
  275. JSONObject about = parsedResp.getJSONObject("about");
  276. JSONArray links = about.getJSONArray("links");
  277. l.debug("Got platform links " + links);
  278. return links.iterator();
  279. } finally {
  280. req.releaseConnection();
  281. }
  282. }
  283. /**
  284. *
  285. *
  286. * @return the WebDav URL from the platform configuration
  287. */
  288. public URL getWebDavURL() {
  289. Iterator<JSONObject> links = getPlatformLinks();
  290. while(links.hasNext()) {
  291. JSONObject link = links.next();
  292. if(link != null && !link.isEmpty() && !link.isNullObject()) {
  293. String category = link.getString("category");
  294. if(category != null && category.length() > 0 && category.equalsIgnoreCase(LINKS_UPLOADS_KEY)) {
  295. try {
  296. String uri = link.getString("link");
  297. if(uri != null && uri.length()>0) {
  298. if(uri.startsWith("/")) {
  299. uri = getServerUrl() + uri;
  300. }
  301. return new URL(uri);
  302. }
  303. else {
  304. throw new InvalidArgumentException("No uploads URL configured for the server: "+category);
  305. }
  306. }
  307. catch (MalformedURLException e) {
  308. throw new InvalidArgumentException("Invalid uploads URL configured for the server: "+category);
  309. }
  310. }
  311. }
  312. }
  313. throw new InvalidArgumentException("No uploads platform link configured for the GoodData cluster.");
  314. }
  315. /**
  316. * Returns a list of project's SLIs
  317. *
  318. * @param projectId project's ID
  319. * @return a list of project's SLIs
  320. * @throws HttpMethodException if there is a communication error
  321. * @throws GdcProjectAccessException if the SLI doesn't exist
  322. */
  323. public List<SLI> getSLIs(String projectId) throws HttpMethodException, GdcProjectAccessException {
  324. l.debug("Getting SLIs from project id=" + projectId);
  325. List<SLI> list = new ArrayList<SLI>();
  326. String ifcUri = getSLIsUri(projectId);
  327. HttpMethod interfacesGet = createGetMethod(ifcUri);
  328. try {
  329. String response = executeMethodOk(interfacesGet);
  330. JSONObject responseObject = JSONObject.fromObject(response);
  331. if (responseObject.isNullObject()) {
  332. l.debug("The project id=" + projectId + " doesn't exist!");
  333. throw new GdcProjectAccessException("The project id=" + projectId + " doesn't exist!");
  334. }
  335. JSONObject interfaceQuery = responseObject.getJSONObject("about");
  336. if (interfaceQuery.isNullObject()) {
  337. l.debug("The project id=" + projectId + " doesn't exist!");
  338. throw new GdcProjectAccessException("The project id=" + projectId + " doesn't exist!");
  339. }
  340. JSONArray links = interfaceQuery.getJSONArray("links");
  341. if (links == null) {
  342. l.debug("The project id=" + projectId + " doesn't exist!");
  343. throw new GdcProjectAccessException("The project id=" + projectId + " doesn't exist!");
  344. }
  345. for (Object ol : links) {
  346. JSONObject link = (JSONObject) ol;
  347. SLI ii = new SLI(link);
  348. list.add(ii);
  349. }
  350. l.debug("Got SLIs " + list + " from project id=" + projectId);
  351. } finally {
  352. interfacesGet.releaseConnection();
  353. }
  354. return list;
  355. }
  356. /**
  357. * Retrieves the SLI columns
  358. *
  359. * @param uri the SLI uri
  360. * @return list of SLI columns
  361. * @throws GdcProjectAccessException if the SLI doesn't exist
  362. * @throws HttpMethodException if there is a communication issue with the GDC platform
  363. */
  364. public List<Column> getSLIColumns(String uri) throws GdcProjectAccessException, HttpMethodException {
  365. l.debug("Retrieveing SLI columns for SLI uri=" + uri);
  366. List<Column> list = new ArrayList<Column>();
  367. HttpMethod sliGet = createGetMethod(getServerUrl() + uri + "/manifest");
  368. try {
  369. String response = executeMethodOk(sliGet);
  370. JSONObject responseObject = JSONObject.fromObject(response);
  371. if (responseObject.isNullObject()) {
  372. l.debug("The SLI uri=" + uri + " doesn't exist!");
  373. throw new GdcProjectAccessException("The SLI uri=" + uri + " doesn't exist!");
  374. }
  375. JSONObject dataSetSLIManifest = responseObject.getJSONObject("dataSetSLIManifest");
  376. if (dataSetSLIManifest.isNullObject()) {
  377. l.debug("The SLI uri=" + uri + " doesn't exist!");
  378. throw new GdcProjectAccessException("The SLI uri=" + uri + " doesn't exist!");
  379. }
  380. JSONArray parts = dataSetSLIManifest.getJSONArray("parts");
  381. for (Object oPart : parts) {
  382. list.add(new Column((JSONObject) oPart));
  383. }
  384. } finally {
  385. sliGet.releaseConnection();
  386. }
  387. return list;
  388. }
  389. /**
  390. * Retrieves the SLI column data type
  391. *
  392. * @param projectId projectId
  393. * @param sliColumnIdentifier SLI column identifier (name in the SLI manifest)
  394. * @return the SLI column datatype
  395. */
  396. public String getSLIColumnDataType(String projectId, String sliColumnIdentifier) {
  397. l.debug("Retrieveing SLI column datatype projectId=" + projectId + " SLI column name=" + sliColumnIdentifier);
  398. MetadataObject o = getMetadataObject(projectId, sliColumnIdentifier);
  399. if (o != null) {
  400. JSONObject c = o.getContent();
  401. if (c != null) {
  402. String type = c.getString("columnType");
  403. if (type != null && type.length() > 0) {
  404. return type;
  405. } else {
  406. l.debug("Error Retrieveing SLI column datatype projectId=" + projectId + " SLI column name=" + sliColumnIdentifier + " No columnType key in the content.");
  407. throw new GdcRestApiException("Error Retrieveing SLI column datatype projectId=" + projectId + " SLI column name=" + sliColumnIdentifier + " No columnType key in the content.");
  408. }
  409. } else {
  410. l.debug("Error Retrieveing SLI column datatype projectId=" + projectId + " SLI column name=" + sliColumnIdentifier + " No content structure.");
  411. throw new GdcRestApiException("Error Retrieveing SLI column datatype projectId=" + projectId + " SLI column name=" + sliColumnIdentifier + " No content structure.");
  412. }
  413. } else {
  414. l.debug("Error Retrieveing SLI column datatype projectId=" + projectId + " SLI column name=" + sliColumnIdentifier + " MD object doesn't exist.");
  415. throw new GdcRestApiException("Error Retrieveing SLI column datatype projectId=" + projectId + " SLI column name=" + sliColumnIdentifier + " MD object doesn't exist.");
  416. }
  417. }
  418. /**
  419. * Retrieves the SLI columns
  420. *
  421. * @param uri the SLI uri
  422. * @return JSON manifest
  423. * @throws GdcProjectAccessException if the SLI doesn't exist
  424. * @throws HttpMethodException if there is a communication issue with the GDC platform
  425. */
  426. public JSONObject getSLIManifest(String uri) throws GdcProjectAccessException, HttpMethodException {
  427. l.debug("Retrieveing SLI columns for SLI uri=" + uri);
  428. List<Column> list = new ArrayList<Column>();
  429. HttpMethod sliGet = createGetMethod(getServerUrl() + uri + "/manifest");
  430. try {
  431. String response = executeMethodOk(sliGet);
  432. JSONObject responseObject = JSONObject.fromObject(response);
  433. if (responseObject.isNullObject()) {
  434. l.debug("The SLI uri=" + uri + " doesn't exist!");
  435. throw new GdcProjectAccessException("The SLI uri=" + uri + " doesn't exist!");
  436. }
  437. return responseObject;
  438. } finally {
  439. sliGet.releaseConnection();
  440. }
  441. }
  442. /**
  443. * Finds a project SLI by it's id
  444. *
  445. * @param id the SLI id
  446. * @param projectId the project id
  447. * @return the SLI
  448. * @throws GdcProjectAccessException if the SLI doesn't exist
  449. * @throws HttpMethodException if there is a communication issue with the GDC platform
  450. */
  451. public SLI getSLIById(String id, String projectId) throws GdcProjectAccessException, HttpMethodException {
  452. l.debug("Get SLI by id=" + id + " project id=" + projectId);
  453. List<SLI> slis = getSLIs(projectId);
  454. return getSLIById(id, slis, projectId);
  455. }
  456. /**
  457. * Finds a project SLI in list of SLI
  458. *
  459. * @param id the SLI id
  460. * @param slis of SLI (related to one project)
  461. * @param projectId the project id
  462. * @return the SLI
  463. * @throws GdcProjectAccessException if the SLI doesn't exist
  464. */
  465. public static SLI getSLIById(String id, List<SLI> slis, String projectId) throws GdcProjectAccessException {
  466. l.debug("Get SLI by id=" + id + " project id=" + projectId);
  467. for (SLI sli : slis) {
  468. if (id.equals(sli.getId())) {
  469. l.debug("Got SLI by id=" + id + " project id=" + projectId);
  470. return sli;
  471. }
  472. }
  473. l.debug("The SLI id=" + id + " doesn't exist in the project id=" + projectId);
  474. throw new GdcProjectAccessException("The SLI id=" + id + " doesn't exist in the project id=" + projectId);
  475. }
  476. /**
  477. * Enumerates all attributes in the project
  478. *
  479. * @param projectId project Id
  480. * @return LIst of attr uris
  481. */
  482. public List<String> enumerateAttributes(String projectId) {
  483. l.debug("Enumerating attributes for project id=" + projectId);
  484. List<String> list = new ArrayList<String>();
  485. String qUri = getProjectMdUrl(projectId) + ATTR_QUERY;
  486. HttpMethod qGet = createGetMethod(qUri);
  487. try {
  488. String qr = executeMethodOk(qGet);
  489. JSONObject q = JSONObject.fromObject(qr);
  490. if (q.isNullObject()) {
  491. l.debug("Enumerating attributes for project id=" + projectId + " failed.");
  492. throw new GdcProjectAccessException("Enumerating attributes for project id=" + projectId + " failed.");
  493. }
  494. JSONObject qry = q.getJSONObject("query");
  495. if (qry.isNullObject()) {
  496. l.debug("Enumerating attributes for project id=" + projectId + " failed.");
  497. throw new GdcProjectAccessException("Enumerating reports for project id=" + projectId + " failed.");
  498. }
  499. JSONArray entries = qry.getJSONArray("entries");
  500. if (entries == null) {
  501. l.debug("Enumerating attributes for project id=" + projectId + " failed.");
  502. throw new GdcProjectAccessException("Enumerating reports for project id=" + projectId + " failed.");
  503. }
  504. for (Object oentry : entries) {
  505. JSONObject entry = (JSONObject) oentry;
  506. list.add(entry.getString("link"));
  507. }
  508. } finally {
  509. qGet.releaseConnection();
  510. }
  511. return list;
  512. }
  513. /**
  514. * Gets attribute PK
  515. *
  516. * @param attrUri attribute URI
  517. * @return list of attribute PKs (columns)
  518. */
  519. public List<JSONObject> getAttributePk(String attrUri) {
  520. List<JSONObject> ret = new ArrayList<JSONObject>();
  521. JSONObject attr = getObjectByUri(attrUri);
  522. JSONObject a = attr.getJSONObject("attribute");
  523. if (a != null && !a.isEmpty() && !a.isEmpty()) {
  524. JSONObject c = a.getJSONObject("content");
  525. if (c != null && !c.isEmpty() && !c.isEmpty()) {
  526. JSONArray pks = c.getJSONArray("pk");
  527. if (pks != null && !pks.isEmpty()) {
  528. Object[] p = pks.toArray();
  529. for (Object pko : p) {
  530. JSONObject pk = (JSONObject) pko;
  531. String columnUri = pk.getString("data");
  532. if (columnUri != null) {
  533. ret.add(getObjectByUri(columnUri));
  534. } else {
  535. l.debug("Error getting attribute PK. No PK data.");
  536. throw new GdcProjectAccessException("Error getting attribute PK. No PK data.");
  537. }
  538. }
  539. }
  540. } else {
  541. l.debug("Error getting attribute PK. No content.");
  542. throw new GdcProjectAccessException("Error getting attribute PK. No content.");
  543. }
  544. } else {
  545. l.debug("Error getting attribute PK. No attribute.");
  546. throw new GdcProjectAccessException("Error getting attribute PK. No attribute.");
  547. }
  548. return ret;
  549. }
  550. /**
  551. * Gets attribute FK
  552. *
  553. * @param attrUri attribute URI
  554. * @return list of attribute FKs (columns)
  555. */
  556. public List<JSONObject> getAttributeFk(String attrUri) {
  557. List<JSONObject> ret = new ArrayList<JSONObject>();
  558. JSONObject attr = getObjectByUri(attrUri);
  559. JSONObject a = attr.getJSONObject("attribute");
  560. if (a != null && !a.isEmpty() && !a.isEmpty()) {
  561. JSONObject c = a.getJSONObject("content");
  562. if (c != null && !c.isEmpty() && !c.isEmpty()) {
  563. if (c.containsKey("fk")) {
  564. JSONArray pks = c.getJSONArray("fk");
  565. if (pks != null && !pks.isEmpty()) {
  566. Object[] p = pks.toArray();
  567. for (Object pko : p) {
  568. JSONObject pk = (JSONObject) pko;
  569. String columnUri = pk.getString("data");
  570. if (columnUri != null && columnUri.trim().length() > 0) {
  571. ret.add(getObjectByUri(columnUri));
  572. } else {
  573. l.debug("Error getting attribute FK. No FK data.");
  574. throw new GdcProjectAccessException("Error getting attribute FK. No FK data.");
  575. }
  576. }
  577. }
  578. }
  579. } else {
  580. l.debug("Error getting attribute FK. No content.");
  581. throw new GdcProjectAccessException("Error getting attribute FK. No content.");
  582. }
  583. } else {
  584. l.debug("Error getting attribute FK. No attribute.");
  585. throw new GdcProjectAccessException("Error getting attribute FK. No attribute.");
  586. }
  587. return ret;
  588. }
  589. /**
  590. * Gets column DB name
  591. *
  592. * @param column column object
  593. * @return column DB name
  594. */
  595. public String getColumnDbName(JSONObject column) {
  596. JSONObject cl = column.getJSONObject("column");
  597. if (cl != null && !cl.isEmpty() && !cl.isEmpty()) {
  598. JSONObject c = cl.getJSONObject("content");
  599. if (c != null && !c.isEmpty() && !c.isEmpty()) {
  600. String cn = c.getString("columnDBName");
  601. if (cn != null && cn.trim().length() > 0) {
  602. return cn;
  603. } else {
  604. l.debug("Error getting column name. No columnDBName.");
  605. throw new GdcProjectAccessException("Error getting column name. No columnDBName.");
  606. }
  607. } else {
  608. l.debug("Error getting column name. No content.");
  609. throw new GdcProjectAccessException("Error getting column name. No content.");
  610. }
  611. } else {
  612. l.debug("Error getting column name. No column.");
  613. throw new GdcProjectAccessException("Error getting column name. No column.");
  614. }
  615. }
  616. /**
  617. * Gets column table name
  618. *
  619. * @param column column object
  620. * @return column table name
  621. */
  622. public String getColumnTableName(JSONObject column) {
  623. JSONObject cl = column.getJSONObject("column");
  624. if (cl != null && !cl.isEmpty() && !cl.isEmpty()) {
  625. JSONObject c = cl.getJSONObject("content");
  626. if (c != null && !c.isEmpty() && !c.isEmpty()) {
  627. String t = c.getString("table");
  628. if (t != null && t.trim().length() > 0) {
  629. JSONObject tbl = getObjectByUri(t);
  630. JSONObject root = tbl.getJSONObject("table");
  631. if (root != null && !root.isEmpty() && !root.isEmpty()) {
  632. c = root.getJSONObject("content");
  633. if (c != null && !c.isEmpty() && !c.isEmpty()) {
  634. String dl = c.getString("activeDataLoad");
  635. if (dl != null && dl.trim().length() > 0) {
  636. JSONObject tdl = getObjectByUri(dl);
  637. root = tdl.getJSONObject("tableDataLoad");
  638. if (root != null && !root.isEmpty() && !root.isEmpty()) {
  639. c = root.getJSONObject("content");
  640. if (c != null && !c.isEmpty() && !c.isEmpty()) {
  641. String tn = c.getString("dataSourceLocation");
  642. if (tn != null && tn.trim().length() > 0) {
  643. return tn;
  644. } else {
  645. l.debug("Error getting column name. No dataSourceLocation.");
  646. throw new GdcProjectAccessException("Error getting column name. No dataSourceLocation.");
  647. }
  648. } else {
  649. l.debug("Error getting column name. No active table data load content.");
  650. throw new GdcProjectAccessException("Error getting column name. No active table data load content.");
  651. }
  652. } else {
  653. l.debug("Error getting column name. No table data load root.");
  654. throw new GdcProjectAccessException("Error getting column name. No table data load root.");
  655. }
  656. } else {
  657. l.debug("Error getting column name. No active data load.");
  658. throw new GdcProjectAccessException("Error getting column name. No active data load.");
  659. }
  660. } else {
  661. l.debug("Error getting column name. No table content.");
  662. throw new GdcProjectAccessException("Error getting column name. No table content.");
  663. }
  664. } else {
  665. l.debug("Error getting column table. No table root.");
  666. throw new GdcProjectAccessException("Error getting column table. No table root.");
  667. }
  668. } else {
  669. l.debug("Error getting column name. No table.");
  670. throw new GdcProjectAccessException("Error getting column name. No table.");
  671. }
  672. } else {
  673. l.debug("Error getting column name. No content.");
  674. throw new GdcProjectAccessException("Error getting column name. No content.");
  675. }
  676. } else {
  677. l.debug("Error getting column name. No column.");
  678. throw new GdcProjectAccessException("Error getting column name. No column.");
  679. }
  680. }
  681. /**
  682. * Enumerates all attributes in the project
  683. *
  684. * @param attrUri attribute URI
  685. * @return attribute object
  686. */
  687. public JSONObject getAttribute(String attrUri) {
  688. l.debug("Getting attribute uri=" + attrUri);
  689. String qUri = getServerUrl() + attrUri;
  690. HttpMethod qGet = createGetMethod(qUri);
  691. try {
  692. String qr = executeMethodOk(qGet);
  693. return JSONObject.fromObject(qr);
  694. } finally {
  695. qGet.releaseConnection();
  696. }
  697. }
  698. /**
  699. * Enumerates all reports on in a project
  700. *
  701. * @param projectId project Id
  702. * @return LIst of report uris
  703. */
  704. public List<String> enumerateReports(String projectId) {
  705. l.debug("Enumerating reports for project id=" + projectId);
  706. List<String> list = new ArrayList<String>();
  707. String qUri = getProjectMdUrl(projectId) + REPORT_QUERY;
  708. HttpMethod qGet = createGetMethod(qUri);
  709. try {
  710. String qr = executeMethodOk(qGet);
  711. JSONObject q = JSONObject.fromObject(qr);
  712. if (q.isNullObject()) {
  713. l.debug("Enumerating reports for project id=" + projectId + " failed.");
  714. throw new GdcProjectAccessException("Enumerating reports for project id=" + projectId + " failed.");
  715. }
  716. JSONObject qry = q.getJSONObject("query");
  717. if (qry.isNullObject()) {
  718. l.debug("Enumerating reports for project id=" + projectId + " failed.");
  719. throw new GdcProjectAccessException("Enumerating reports for project id=" + projectId + " failed.");
  720. }
  721. JSONArray entries = qry.getJSONArray("entries");
  722. if (entries == null) {
  723. l.debug("Enumerating reports for project id=" + projectId + " failed.");
  724. throw new GdcProjectAccessException("Enumerating reports for project id=" + projectId + " failed.");
  725. }
  726. for (Object oentry : entries) {
  727. JSONObject entry = (JSONObject) oentry;
  728. int deprecated = entry.getInt("deprecated");
  729. if (deprecated == 0)
  730. list.add(entry.getString("link"));
  731. }
  732. } finally {
  733. qGet.releaseConnection();
  734. }
  735. return list;
  736. }
  737. private String getProjectIdFromObjectUri(String uri) {
  738. Pattern regexp = Pattern.compile("gdc/md/.*?/");
  739. Matcher m = regexp.matcher(uri);
  740. if (m.find()) {
  741. return m.group().split("/")[2];
  742. } else {
  743. l.debug("The passed string '" + uri + "' doesn't have the GoodData URI structure!");
  744. throw new InvalidParameterException("The passed string '" + uri + "' doesn't have the GoodData URI structure!");
  745. }
  746. }
  747. /**
  748. * Computes the metric value
  749. *
  750. * @param metricUri metric URI
  751. * @return the metric value
  752. */
  753. public double computeMetric(String metricUri) {
  754. l.debug("Computing metric uri=" + metricUri);
  755. double retVal = 0;
  756. String projectId = getProjectIdFromObjectUri(metricUri);
  757. JSONObject reportDefinition = new JSONObject();
  758. JSONObject metric = new JSONObject();
  759. metric.put("alias", "");
  760. metric.put("uri", metricUri);
  761. JSONArray metrics = new JSONArray();
  762. metrics.add(metric);
  763. JSONArray columns = new JSONArray();
  764. columns.add("metricGroup");
  765. JSONObject grid = new JSONObject();
  766. grid.put("metrics", metrics);
  767. grid.put("columns", columns);
  768. grid.put("rows", new JSONArray());
  769. grid.put("columnWidths", new JSONArray());
  770. JSONObject sort = new JSONObject();
  771. sort.put("columns", new JSONArray());
  772. sort.put("rows", new JSONArray());
  773. grid.put("sort", sort);
  774. JSONObject content = new JSONObject();
  775. content.put("grid", grid);
  776. content.put("filters", new JSONArray());
  777. content.put("format", "grid");
  778. reportDefinition.put("content", content);
  779. JSONObject meta = new JSONObject();
  780. meta.put("category", "reportDefinition");
  781. meta.put("title", "N/A");
  782. reportDefinition.put("meta", meta);
  783. MetadataObject obj = new MetadataObject();
  784. obj.put("reportDefinition", reportDefinition);
  785. MetadataObject resp = new MetadataObject(createMetadataObject(projectId, obj));
  786. int retryCnt = Constants.MAX_RETRY;
  787. boolean hasFinished = false;
  788. while (retryCnt-- > 0 && !hasFinished) {
  789. try {
  790. String dataResultUri = executeReportDefinition(resp.getUri());
  791. JSONObject result = getObjectByUri(dataResultUri);
  792. hasFinished = true;
  793. if (result != null && !result.isEmpty() && !result.isNullObject()) {
  794. JSONObject xtabData = result.getJSONObject("xtab_data");
  795. if (xtabData != null && !xtabData.isEmpty() && !xtabData.isNullObject()) {
  796. JSONArray data = xtabData.getJSONArray("data");
  797. if (data != null && !data.isEmpty()) {
  798. retVal = data.getJSONArray(0).getDouble(0);
  799. } else {
  800. l.debug("Can't compute the metric. No data structure in result.");
  801. throw new InvalidParameterException("Can't compute the metric. No data structure in result.");
  802. }
  803. } else {
  804. l.debug("Can't compute the metric. No xtab_data structure in result.");
  805. throw new InvalidParameterException("Can't compute the metric. No xtab_data structure in result.");
  806. }
  807. } else {
  808. l.debug("Can't compute the metric. No result from XTAB.");
  809. throw new InvalidParameterException("Can't compute the metric. No result from XTAB.");
  810. }
  811. } catch (HttpMethodNotFinishedYetException e) {
  812. l.debug("computeMetric: Waiting for DataResult");
  813. try {
  814. Thread.sleep(Constants.POLL_INTERVAL);
  815. } catch (InterruptedException ex) {
  816. // do nothing
  817. }
  818. }
  819. }
  820. l.debug("Metric uri=" + metricUri + " computed. Result is " + retVal);
  821. return retVal;
  822. }
  823. /**
  824. * Computes a simple report and returns the report text
  825. *
  826. * @param reportUri report URI
  827. * @return the report rendered in text
  828. */
  829. public String computeReport(String reportUri) {
  830. l.debug("Computing report uri=" + reportUri);
  831. String retVal = "";
  832. int retryCnt = Constants.MAX_RETRY;
  833. boolean hasFinished = false;
  834. while (retryCnt-- > 0 && !hasFinished) {
  835. try {
  836. String dataResultUri = executeReport(reportUri);
  837. JSONObject result = getObjectByUri(dataResultUri);
  838. hasFinished = true;
  839. if (result != null && !result.isEmpty() && !result.isNullObject()) {
  840. JSONObject xtabData = result.getJSONObject("xtab_data");
  841. if (xtabData != null && !xtabData.isEmpty() && !xtabData.isNullObject()) {
  842. JSONArray data = xtabData.getJSONArray("data");
  843. if (data != null && !data.isEmpty()) {
  844. double[] values = new double[data.size()];
  845. for (int i = 0; i < data.size(); i++) {
  846. JSONArray vals = data.getJSONArray(i);
  847. values[i] = vals.getDouble(0);
  848. }
  849. JSONObject rows = xtabData.getJSONObject("rows");
  850. if (rows != null && !rows.isEmpty() && !rows.isNullObject()) {
  851. JSONArray lookups = rows.getJSONArray("lookups");
  852. if (lookups != null && !lookups.isEmpty()) {
  853. Map<String, String> attributes = new HashMap<String, String>();
  854. JSONObject lkpData = lookups.getJSONObject(0);
  855. for (Object key : lkpData.keySet()) {
  856. Object value = lkpData.get(key);
  857. if (key != null && value != null)
  858. attributes.put(key.toString(), value.toString());
  859. }
  860. JSONObject tree = rows.getJSONObject("tree");
  861. if (tree != null && !tree.isEmpty() && !tree.isNullObject()) {
  862. Map<String, Integer> indexes = new HashMap<String, Integer>();
  863. JSONObject index = tree.getJSONObject("index");
  864. if (index != null && !index.isEmpty()) {
  865. for (Object key : index.keySet()) {
  866. if (key != null) {
  867. JSONArray valIdxs = index.getJSONArray(key.toString());
  868. if (valIdxs != null && !valIdxs.isEmpty()) {
  869. indexes.put(key.toString(), valIdxs.getInt(0));
  870. }
  871. }
  872. }
  873. JSONArray children = tree.getJSONArray("children");
  874. if (children != null && !children.isEmpty()) {
  875. for (int i = 0; i < children.size(); i++) {
  876. JSONObject c = children.getJSONObject(i);
  877. String id = c.getString("id");
  878. if (id != null && id.length() > 0) {
  879. String attribute = attributes.get(id);
  880. int v = indexes.get(id);
  881. double vl = values[v];
  882. if (retVal.length() > 0) {
  883. retVal += ", " + attribute + " : " + vl;
  884. } else {
  885. retVal += attribute + " : " + vl;
  886. }
  887. } else {
  888. l.debug("Can't compute the report. No id in children.");
  889. throw new InvalidParameterException("Can't compute the report. No id in children.");
  890. }
  891. }
  892. } else {
  893. l.debug("Can't compute the report. No tree structure in result.");
  894. throw new InvalidParameterException("Can't compute the report. No tree structure in result.");
  895. }
  896. } else {
  897. l.debug("Can't compute the report. No index structure in result.");
  898. throw new InvalidParameterException("Can't compute the report. No index structure in result.");
  899. }
  900. } else {
  901. l.debug("Can't compute the report. No tree structure in result.");
  902. throw new InvalidParameterException("Can't compute the report. No tree structure in result.");
  903. }
  904. } else {
  905. l.debug("Can't compute the report. No lookups structure in result.");
  906. throw new InvalidParameterException("Can't compute the report. No lookups structure in result.");
  907. }
  908. } else {
  909. l.debug("Can't compute the report. No rows structure in result.");
  910. throw new InvalidParameterException("Can't compute the report. No rows structure in result.");
  911. }
  912. } else {
  913. l.debug("Can't compute the report. No data structure in result.");
  914. throw new InvalidParameterException("Can't compute the report. No data structure in result.");
  915. }
  916. } else {
  917. l.debug("Can't compute the report. No xtab_data structure in result.");
  918. throw new InvalidParameterException("Can't compute the report. No xtab_data structure in result.");
  919. }
  920. } else {
  921. l.debug("Can't compute the report. No result from XTAB.");
  922. throw new InvalidParameterException("Can't compute the metric. No result from XTAB.");
  923. }
  924. } catch (HttpMethodNotFinishedYetException e) {
  925. l.debug("computeReport: Waiting for DataResult");
  926. try {
  927. Thread.sleep(Constants.POLL_INTERVAL);
  928. } catch (InterruptedException ex) {
  929. // do nothing
  930. }
  931. }
  932. }
  933. l.debug("Report uri=" + reportUri + " computed.");
  934. return retVal;
  935. }
  936. /**
  937. * Report definition to execute
  938. *
  939. * @param reportDefUri report definition to execute
  940. */
  941. public String executeReportDefinition(String reportDefUri) {
  942. l.debug("Executing report definition uri=" + reportDefUri);
  943. PostMethod execPost = createPostMethod(getServerUrl() + EXECUTOR);
  944. JSONObject execDef = new JSONObject();
  945. execDef.put("reportDefinition", reportDefUri);
  946. JSONObject exec = new JSONObject();
  947. exec.put("report_req", execDef);
  948. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(exec.toString().getBytes()));
  949. execPost.setRequestEntity(request);
  950. try {
  951. String task = executeMethodOk(execPost);
  952. if (task != null && task.length() > 0) {
  953. JSONObject tr = JSONObject.fromObject(task);
  954. if (tr.isNullObject()) {
  955. l.debug("Executing report definition uri=" + reportDefUri + " failed. Returned invalid result result=" + tr);
  956. throw new GdcRestApiException("Executing report definition uri=" + reportDefUri + " failed. " +
  957. "Returned invalid result result=" + tr);
  958. }
  959. JSONObject reportResult = tr.getJSONObject("execResult");
  960. if (reportResult.isNullObject()) {
  961. l.debug("Executing report definition uri=" + reportDefUri + " failed. Returned invalid result result=" + tr);
  962. throw new GdcRestApiException("Executing report definition uri=" + reportDefUri + " failed. " +
  963. "Returned invalid result result=" + tr);
  964. }
  965. String dataResult = reportResult.getString("dataResult");
  966. if (dataResult == null || dataResult.length()<=0) {
  967. l.debug("Executing report definition uri=" + reportDefUri + " failed. Returned invalid result result=" + tr);
  968. throw new GdcRestApiException("Executing report definition uri=" + reportDefUri + " failed. " +
  969. "Returned invalid result result=" + tr);
  970. }
  971. return dataResult;
  972. } else {
  973. l.debug("Executing report definition uri=" + reportDefUri + " failed. Returned invalid task link uri=" + task);
  974. throw new GdcRestApiException("Executing report definition uri=" + reportDefUri +
  975. " failed. Returned invalid task link uri=" + task);
  976. }
  977. } catch (HttpMethodException ex) {
  978. l.debug("Executing report definition uri=" + reportDefUri + " failed.", ex);
  979. throw new GdcRestApiException("Executing report definition uri=" + reportDefUri + " failed.");
  980. } finally {
  981. execPost.releaseConnection();
  982. }
  983. }
  984. /**
  985. * Report to execute
  986. *
  987. * @param reportUri report definition to execute
  988. */
  989. public String executeReport(String reportUri) {
  990. l.debug("Executing report uri=" + reportUri);
  991. PostMethod execPost = createPostMethod(getServerUrl() + EXECUTOR);
  992. JSONObject execDef = new JSONObject();
  993. execDef.put("report", reportUri);
  994. JSONObject exec = new JSONObject();
  995. exec.put("report_req", execDef);
  996. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(exec.toString().getBytes()));
  997. execPost.setRequestEntity(request);
  998. String taskLink = null;
  999. try {
  1000. String task = executeMethodOk(execPost);
  1001. if (task != null && task.length() > 0) {
  1002. JSONObject tr = JSONObject.fromObject(task);
  1003. if (tr.isNullObject()) {
  1004. l.debug("Executing report uri=" + reportUri + " failed. Returned invalid result=" + tr);
  1005. throw new GdcRestApiException("Executing report uri=" + reportUri + " failed. " +
  1006. "Returned invalid result result=" + tr);
  1007. }
  1008. JSONObject reportResult = tr.getJSONObject("execResult");
  1009. if (reportResult.isNullObject()) {
  1010. l.debug("Executing report uri=" + reportUri + " failed. Returned invalid result=" + tr);
  1011. throw new GdcRestApiException("Executing report uri=" + reportUri + " failed. " +
  1012. "Returned invalid result result=" + tr);
  1013. }
  1014. String dataResult = reportResult.getString("dataResult");
  1015. if (dataResult == null || dataResult.length()<=0) {
  1016. l.debug("Executing report uri=" + reportUri + " failed. Returned invalid dataResult=" + tr);
  1017. throw new GdcRestApiException("Executing report uri=" + reportUri + " failed. " +
  1018. "Returned invalid dataResult=" + tr);
  1019. }
  1020. return dataResult;
  1021. } else {
  1022. l.debug("Executing report uri=" + reportUri + " failed. Returned invalid task link uri=" + task);
  1023. throw new GdcRestApiException("Executing report uri=" + reportUri +
  1024. " failed. Returned invalid task link uri=" + task);
  1025. }
  1026. } catch (HttpMethodException ex) {
  1027. l.debug("Executing report uri=" + reportUri + " failed.", ex);
  1028. throw new GdcRestApiException("Executing report uri=" + reportUri + " failed.");
  1029. } finally {
  1030. execPost.releaseConnection();
  1031. }
  1032. }
  1033. /**
  1034. * Export a report result
  1035. *
  1036. * @param resultUri report result to export
  1037. * @param format export format (pdf | xls | png | csv)
  1038. */
  1039. public byte[] exportReportResult(String resultUri, String format) {
  1040. l.debug("Exporting report result uri=" + resultUri);
  1041. PostMethod execPost = createPostMethod(getServerUrl() + EXPORT_EXECUTOR);
  1042. JSONObject execDef = new JSONObject();
  1043. execDef.put("report", resultUri);
  1044. execDef.put("format", format);
  1045. JSONObject exec = new JSONObject();
  1046. exec.put("result_req", execDef);
  1047. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(exec.toString().getBytes()));
  1048. execPost.setRequestEntity(request);
  1049. String taskLink = null;
  1050. try {
  1051. String task = executeMethodOk(execPost);
  1052. if (task != null && task.length() > 0) {
  1053. JSONObject tr = JSONObject.fromObject(task);
  1054. if (tr.isNullObject()) {
  1055. l.debug("Exporting report result uri=" + resultUri + " failed. Returned invalid result=" + tr);
  1056. throw new GdcRestApiException("Exporting report result uri=" + resultUri + " failed. " +
  1057. "Returned invalid result=" + tr);
  1058. }
  1059. String uri = tr.getString("uri");
  1060. if (uri != null && uri.length() > 0) {
  1061. return getReportResult(uri);
  1062. } else {
  1063. l.debug("Exporting report result uri=" + resultUri + " failed. Returned invalid result=" + tr);
  1064. throw new GdcRestApiException("Exporting report result uri=" + resultUri + " failed. " +
  1065. "Returned invalid result=" + tr);
  1066. }
  1067. } else {
  1068. l.debug("Exporting report result uri=" + resultUri + " failed. Returned invalid task link uri=" + task);
  1069. throw new GdcRestApiException("Exporting report result uri=" + resultUri +
  1070. " failed. Returned invalid task link uri=" + task);
  1071. }
  1072. } catch (HttpMethodException ex) {
  1073. l.debug("Exporting report result uri=" + resultUri + " failed.", ex);
  1074. throw new GdcRestApiException("Exporting report result uri=" + resultUri + " failed.");
  1075. } finally {
  1076. execPost.releaseConnection();
  1077. }
  1078. }
  1079. /**
  1080. * Retrieves the report export result
  1081. *
  1082. * @param uri the export result
  1083. * @return attribute object
  1084. */
  1085. public byte[] getReportResult(String uri) {
  1086. l.debug("Retrieving export result uri=" + uri);
  1087. byte[] buf = null;
  1088. String qUri = getServerUrl() + uri;
  1089. boolean finished = false;
  1090. do {
  1091. HttpMethod qGet = createGetMethod(qUri);
  1092. try {
  1093. executeMethodOkOnly(qGet);
  1094. finished = true;
  1095. buf = qGet.getResponseBody();
  1096. } catch (HttpMethodNotFinishedYetException e) {
  1097. l.debug("Waiting for exporter to finish.");
  1098. try {
  1099. Thread.currentThread().sleep(Constants.POLL_INTERVAL);
  1100. } catch (InterruptedException ex) {
  1101. // do nothing
  1102. }
  1103. } catch (IOException e) {
  1104. l.debug("Network error during the report result export.", e);
  1105. throw new GdcRestApiException("Network error during the report result export.", e);
  1106. } finally {
  1107. qGet.releaseConnection();
  1108. }
  1109. } while (!finished);
  1110. return buf;
  1111. }
  1112. /**
  1113. * Kicks the GDC platform to inform it that the FTP transfer is finished.
  1114. *
  1115. * @param projectId the project's ID
  1116. * @param remoteDir the remote (FTP) directory that contains the data
  1117. * @return the link that is used for polling the loading progress
  1118. * @throws GdcRestApiException
  1119. */
  1120. public String startLoading(String projectId, String remoteDir) throws GdcRestApiException {
  1121. l.debug("Initiating data load project id=" + projectId + " remoteDir=" + remoteDir);
  1122. PostMethod pullPost = createPostMethod(getProjectMdUrl(projectId) + PULL_URI);
  1123. JSONObject pullStructure = getPullStructure(remoteDir);
  1124. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(pullStructure.toString().getBytes()));
  1125. pullPost.setRequestEntity(request);
  1126. String taskLink = null;
  1127. try {
  1128. String response = executeMethodOk(pullPost);
  1129. JSONObject responseObject = JSONObject.fromObject(response);
  1130. taskLink = responseObject.getJSONObject("pullTask").getString("uri");
  1131. } catch (HttpMethodException ex) {
  1132. throw new GdcRestApiException("Loading fails: " + ex.getMessage());
  1133. } finally {
  1134. pullPost.releaseConnection();
  1135. }
  1136. l.debug("Data load project id=" + projectId + " remoteDir=" + remoteDir + " initiated. Status is on uri=" + taskLink);
  1137. return taskLink;
  1138. }
  1139. /**
  1140. * Returns the pull API JSON structure
  1141. *
  1142. * @param directory the remote directory
  1143. * @return the pull API JSON structure
  1144. */
  1145. private JSONObject getPullStructure(String directory) {
  1146. JSONObject pullStructure = new JSONObject();
  1147. pullStructure.put("pullIntegration", directory);
  1148. return pullStructure;
  1149. }
  1150. /**
  1151. * Checks if the loading is finished
  1152. *
  1153. * @param link the link returned from the start loading
  1154. * @return the loading status
  1155. */
  1156. public String getLoadingStatus(String link) throws HttpMethodException {
  1157. l.debug("Getting data loading status uri=" + link);
  1158. HttpMethod ptm = createGetMethod(getServerUrl() + link);
  1159. try {
  1160. String response = executeMethodOk(ptm);
  1161. JSONObject task = JSONObject.fromObject(response);
  1162. String status = task.getString("taskStatus");
  1163. l.debug("Loading status=" + status);
  1164. return status;
  1165. } finally {
  1166. ptm.releaseConnection();
  1167. }
  1168. }
  1169. /**
  1170. * Create a new GoodData project
  1171. *
  1172. * @param name project name
  1173. * @param desc project description
  1174. * @param templateUri project template uri
  1175. * @param driver underlying database driver
  1176. * @param accessToken access token
  1177. * @return the project Id
  1178. * @throws GdcRestApiException
  1179. */
  1180. public String createProject(String name, String desc, String templateUri, String driver, String accessToken) throws GdcRestApiException {
  1181. l.debug("Creating project name=" + name);
  1182. PostMethod createProjectPost = createPostMethod(getServerUrl() + PROJECTS_URI);
  1183. JSONObject createProjectStructure = getCreateProject(name, desc, templateUri, driver, accessToken);
  1184. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(
  1185. createProjectStructure.toString().getBytes()));
  1186. createProjectPost.setRequestEntity(request);
  1187. String uri = null;
  1188. try {
  1189. String response = executeMethodOk(createProjectPost);
  1190. JSONObject responseObject = JSONObject.fromObject(response);
  1191. uri = responseObject.getString("uri");
  1192. } catch (HttpMethodException ex) {
  1193. l.debug("Creating project fails: ", ex);
  1194. throw new GdcRestApiException("Creating project fails: ", ex);
  1195. } finally {
  1196. createProjectPost.releaseConnection();
  1197. }
  1198. if (uri != null && uri.length() > 0) {
  1199. String id = getProjectId(uri);
  1200. l.debug("Created project id=" + id);
  1201. return id;
  1202. }
  1203. l.debug("Error creating project.");
  1204. throw new GdcRestApiException("Error creating project.");
  1205. }
  1206. /**
  1207. * Returns the create project JSON structure
  1208. *
  1209. * @param name project name
  1210. * @param desc project description
  1211. * @param templateUri project template uri
  1212. * @param driver underlying database driver
  1213. * @param accessToken access token
  1214. * @return the create project JSON structure
  1215. */
  1216. private JSONObject getCreateProject(String name, String desc, String templateUri, String driver, String accessToken) {
  1217. JSONObject meta = new JSONObject();
  1218. meta.put("title", name);
  1219. meta.put("summary", desc);
  1220. if (templateUri != null && templateUri.length() > 0) {
  1221. meta.put("projectTemplate", templateUri);
  1222. }
  1223. JSONObject content = new JSONObject();
  1224. //content.put("state", "ENABLED");
  1225. content.put("guidedNavigation", "1");
  1226. if(driver != null && driver.length()>0) {
  1227. content.put("driver", driver);
  1228. }
  1229. if(accessToken != null && accessToken.length()>0) {
  1230. content.put("authorizationToken", accessToken);
  1231. }
  1232. JSONObject project = new JSONObject();
  1233. project.put("meta", meta);
  1234. project.put("content", content);
  1235. JSONObject createStructure = new JSONObject();
  1236. createStructure.put("project", project);
  1237. return createStructure;
  1238. }
  1239. /**
  1240. * Returns the project status
  1241. *
  1242. * @param id project ID
  1243. * @return current project status
  1244. */
  1245. public String getProjectStatus(String id) {
  1246. l.debug("Getting project status for project " + id);
  1247. HttpMethod req = createGetMethod(getServerUrl() + PROJECTS_URI + "/" + id);
  1248. try {
  1249. String resp = executeMethodOk(req);
  1250. JSONObject parsedResp = JSONObject.fromObject(resp);
  1251. JSONObject project = parsedResp.getJSONObject("project");
  1252. JSONObject content = project.getJSONObject("content");
  1253. String state = content.getString("state");
  1254. return state;
  1255. } catch (HttpMethodException e) {
  1256. l.debug("The project id=" + id + " doesn't exists.");
  1257. throw new GdcProjectAccessException("The project id=" + id + " doesn't exists.");
  1258. } finally {
  1259. req.releaseConnection();
  1260. }
  1261. }
  1262. /**
  1263. * Drops a GoodData project
  1264. *
  1265. * @param projectId project id
  1266. * @throws GdcRestApiException
  1267. */
  1268. public void dropProject(String projectId) throws GdcRestApiException {
  1269. l.debug("Dropping project id=" + projectId);
  1270. DeleteMethod dropProjectDelete = createDeleteMethod(getServerUrl() + PROJECTS_URI + "/"+projectId);
  1271. try {
  1272. executeMethodOk(dropProjectDelete);
  1273. } catch (HttpMethodException ex) {
  1274. l.debug("Dropping project id=" + projectId + " failed.", ex);
  1275. throw new GdcRestApiException("Dropping project id=" + projectId + " failed.", ex);
  1276. } finally {
  1277. dropProjectDelete.releaseConnection();
  1278. }
  1279. l.debug("Dropped project id=" + projectId);
  1280. }
  1281. /**
  1282. * Retrieves the project id from the URI returned by the create project
  1283. *
  1284. * @param uri the create project URI
  1285. * @return project id
  1286. * @throws GdcRestApiException in case the project doesn't exist
  1287. */
  1288. protected String getProjectId(String uri) throws GdcRestApiException {
  1289. l.debug("Getting project id by uri=" + uri);
  1290. if (uri != null && uri.length() > 0) {
  1291. String[] cs = uri.split("/");
  1292. if (cs != null && cs.length > 0) {
  1293. l.debug("Got project id=" + cs[cs.length - 1] + " by uri=" + uri);
  1294. return cs[cs.length - 1];
  1295. }
  1296. }
  1297. l.debug("Can't get project from " + uri);
  1298. throw new GdcRestApiException("Can't get project from " + uri);
  1299. }
  1300. /**
  1301. * Executes the MAQL and creates/modifies the project's LDM
  1302. *
  1303. * @param projectId the project's ID
  1304. * @param maql String with the MAQL statements
  1305. * @return result String
  1306. * @throws GdcRestApiException
  1307. */
  1308. public String[] executeMAQL(String projectId, String maql) throws GdcRestApiException {
  1309. l.debug("Executing MAQL projectId=" + projectId + " MAQL:\n" + maql);
  1310. List<String> results = new ArrayList<String>();
  1311. for (String maqlSplit : splitMAQL(maql)) {
  1312. PostMethod maqlPost = createPostMethod(getProjectMdUrl(projectId) + MAQL_EXEC_URI);
  1313. JSONObject maqlStructure = getMAQLExecStructure(maqlSplit);
  1314. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(
  1315. maqlStructure.toString().getBytes()));
  1316. maqlPost.setRequestEntity(request);
  1317. try {
  1318. String response = executeMethodOk(maqlPost);
  1319. JSONObject responseObject = JSONObject.fromObject(response);
  1320. JSONArray uris = responseObject.getJSONArray("uris");
  1321. List<String> jsonResult = JSONArray.toList(uris, String.class);
  1322. results.addAll(jsonResult);
  1323. } catch (HttpMethodException ex) {
  1324. l.debug("MAQL execution: ", ex);
  1325. throw new GdcRestApiException("MAQL execution: " + ex.getMessage(), ex);
  1326. } finally {
  1327. maqlPost.releaseConnection();
  1328. }
  1329. }
  1330. return results.toArray(new String[results.size()]);
  1331. }
  1332. /**
  1333. * Split maql if size of executed script is likely to exceed 60s timeout on backend.
  1334. *
  1335. * @see http://support.gooddata.com/requests/17258
  1336. * @param maql the maql
  1337. * @return the string[]
  1338. */
  1339. protected List<String> splitMAQL(String maql) {
  1340. List<String> splits = new ArrayList<String>();
  1341. List<String> maqlLines = Arrays.asList(NEWLINE_SEPARATOR_PARSER.split(maql));
  1342. // split if we have more than 50 lines of MAQL
  1343. if (maqlLines.size() >= 1000) {
  1344. // bisect: left part..
  1345. int halfSize =maqlLines.size()/2;
  1346. splits.addAll(splitMAQL(StringUtils.join(maqlLines.subList(0,halfSize), "\n")));
  1347. // .. and right part
  1348. splits.addAll(splitMAQL(StringUtils.join( maqlLines.subList(halfSize, maqlLines.size()),"\n")));
  1349. }else {
  1350. // small enough, add string as a whole
  1351. splits.add( StringUtils.join(maqlLines, "\n"));
  1352. }
  1353. return splits;
  1354. }
  1355. /**
  1356. * Executes the MAQL and creates/modifies the project's LDM asynchronously
  1357. *
  1358. * @param projectId the project's ID
  1359. * @param maql String with the MAQL statements
  1360. * @return result String
  1361. * @throws GdcRestApiException
  1362. */
  1363. public void executeMAQLAsync(String projectId, String maql) throws GdcRestApiException {
  1364. l.debug("Executing async MAQL projectId=" + projectId + " MAQL:\n" + maql);
  1365. PostMethod maqlPost = createPostMethod(getProjectMdUrl(projectId) + MAQL_ASYNC_EXEC_URI);
  1366. JSONObject maqlStructure = getMAQLExecStructure(maql);
  1367. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(
  1368. maqlStructure.toString().getBytes()));
  1369. maqlPost.setRequestEntity(request);
  1370. String result = null;
  1371. try {
  1372. String response = executeMethodOk(maqlPost);
  1373. JSONObject responseObject = JSONObject.fromObject(response);
  1374. JSONArray uris = responseObject.getJSONArray("entries");
  1375. String taskmanUri = "";
  1376. for(Object ouri : uris) {
  1377. JSONObject uri = (JSONObject)ouri;
  1378. String category = uri.getString("category");
  1379. if(category.equals("tasks-status")) {
  1380. taskmanUri = uri.getString("link");
  1381. }
  1382. }
  1383. if(taskmanUri != null && taskmanUri.length()>0) {
  1384. l.debug("Checking async MAQL DDL execution status.");
  1385. TaskmanStatus status = new TaskmanStatus("",new String[]{});
  1386. while (!"OK".equalsIgnoreCase(status.getStatus()) && !"ERROR".equalsIgnoreCase(status.getStatus()) &&
  1387. !"WARNING".equalsIgnoreCase(status.getStatus())) {
  1388. status = getDetailedTaskManStatus(taskmanUri);
  1389. l.debug("Async MAQL DDL status = " + status.getStatus());
  1390. Thread.sleep(Constants.POLL_INTERVAL);
  1391. }
  1392. l.info("Async MAQL DDL finished with status " + status.getStatus());
  1393. if (!("OK".equalsIgnoreCase(status.getStatus()) || "WARNING".equalsIgnoreCase(status.getStatus()))) {
  1394. String[] messages = status.getMessage();
  1395. String message = "";
  1396. for(String msg : messages) {
  1397. if(message.length()>0) message += "\n";
  1398. message += msg;
  1399. }
  1400. throw new GdcRestApiException("Async MAQL execution failed with status "+status.getStatus() +
  1401. ". Errors: "+message);
  1402. }
  1403. }
  1404. } catch (HttpMethodException ex) {
  1405. l.debug("MAQL execution: ", ex);
  1406. throw new GdcRestApiException("MAQL execution: " + ex.getMessage(), ex);
  1407. } catch (InterruptedException e) {
  1408. throw new InternalErrorException(e);
  1409. } finally {
  1410. maqlPost.releaseConnection();
  1411. }
  1412. }
  1413. public static class ProjectExportResult {
  1414. private String taskUri;
  1415. private String exportToken;
  1416. public String getTaskUri() {
  1417. return taskUri;
  1418. }
  1419. public void setTaskUri(String taskUri) {
  1420. this.taskUri = taskUri;
  1421. }
  1422. public String getExportToken() {
  1423. return exportToken;
  1424. }
  1425. public void setExportToken(String exportToken) {
  1426. this.exportToken = exportToken;
  1427. }
  1428. }
  1429. /**
  1430. * Exports the project
  1431. *
  1432. * @param projectId the project's ID
  1433. * @param exportUsers flag
  1434. * @param exportData flag
  1435. * @param authorizedUsers list of authorized users
  1436. * @return result the taskUri and the export token
  1437. * @throws GdcRestApiException
  1438. */
  1439. public ProjectExportResult exportProject(String projectId, boolean exportUsers, boolean exportData, String[] authorizedUsers)
  1440. throws GdcRestApiException {
  1441. l.debug("Exporting project projectId=" + projectId + " users:" + exportUsers + " data:" + exportData + " authorized users:" +
  1442. authorizedUsers);
  1443. PostMethod req = createPostMethod(getProjectMdUrl(projectId) + PROJECT_EXPORT_URI);
  1444. JSONObject param = getProjectExportStructure(exportUsers, exportData, authorizedUsers);
  1445. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(
  1446. param.toString().getBytes()));
  1447. req.setRequestEntity(request);
  1448. ProjectExportResult result = null;
  1449. try {
  1450. String response = executeMethodOk(req);
  1451. result = new ProjectExportResult();
  1452. JSONObject responseObject = JSONObject.fromObject(response);
  1453. JSONObject exportArtifact = responseObject.getJSONObject("exportArtifact");
  1454. JSONObject status = exportArtifact.getJSONObject("status");
  1455. result.setTaskUri(status.getString("uri"));
  1456. result.setExportToken(exportArtifact.getString("token"));
  1457. return result;
  1458. } catch (HttpMethodException ex) {
  1459. l.debug("Error exporting project", ex);
  1460. throw new GdcRestApiException("Error exporting project", ex);
  1461. } finally {
  1462. req.releaseConnection();
  1463. }
  1464. }
  1465. private JSONObject getProjectExportStructure(boolean exportUsers, boolean exportData, String[] authorizedUsers) {
  1466. JSONObject param = new JSONObject();
  1467. JSONObject exportProject = new JSONObject();
  1468. exportProject.put("exportUsers", (exportUsers) ? (1) : (0));
  1469. exportProject.put("exportData", (exportData) ? (1) : (0));
  1470. if (authorizedUsers != null && authorizedUsers.length > 0) {
  1471. JSONArray aUsers = new JSONArray();
  1472. aUsers.addAll(Arrays.asList(authorizedUsers));
  1473. exportProject.put("authorizedUsers", aUsers);
  1474. }
  1475. param.put("exportProject", exportProject);
  1476. return param;
  1477. }
  1478. private GdcRole getRoleFromUri(String roleUri) {
  1479. l.debug("Getting role from uri: " + roleUri);
  1480. HttpMethod req = createGetMethod( getServerUrl() + roleUri);
  1481. try {
  1482. String resp = executeMethodOk(req);
  1483. JSONObject parsedResp = JSONObject.fromObject(resp);
  1484. if (parsedResp == null || parsedResp.isNullObject() || parsedResp.isEmpty()) {
  1485. l.debug("Can't getRoleFromUri for uri " + roleUri + ". Invalid response.");
  1486. throw new GdcRestApiException("Can't getRoleFromUri for uri " + roleUri + ". Invalid response.");
  1487. }
  1488. return new GdcRole(parsedResp);
  1489. } catch (HttpMethodException ex) {
  1490. l.debug("Error getRoleFromUri.", ex);
  1491. throw new GdcRestApiException("Error getRoleFromUri", ex);
  1492. } finally {
  1493. req.releaseConnection();
  1494. }
  1495. }
  1496. private GdcUser getUserFromUri(String userUri) {
  1497. l.debug("Getting user from uri: " + userUri);
  1498. HttpMethod req = createGetMethod( getServerUrl() + userUri);
  1499. try {
  1500. String resp = executeMethodOk(req);
  1501. JSONObject parsedResp = JSONObject.fromObject(resp);
  1502. if (parsedResp == null || parsedResp.isNullObject() || parsedResp.isEmpty()) {
  1503. l.debug("Can't getUserFromUri for uri " + userUri + ". Invalid response.");
  1504. throw new GdcRestApiException("Can't getUserFromUri for uri " + userUri + ". Invalid response.");
  1505. }
  1506. return new GdcUser(parsedResp);
  1507. } catch (HttpMethodException ex) {
  1508. l.debug("Error getUserFromUri.", ex);
  1509. throw new GdcRestApiException("Error getUserFromUri", ex);
  1510. } finally {
  1511. req.releaseConnection();
  1512. }
  1513. }
  1514. public static class GdcRole{
  1515. private String name;
  1516. private String identifier;
  1517. private String uri;
  1518. public GdcRole() {
  1519. }
  1520. public GdcRole(JSONObject role) {
  1521. if (role == null || role.isEmpty() || role.isNullObject()) {
  1522. throw new GdcRestApiException("Can't extract role from JSON. The JSON is empty.");
  1523. }
  1524. JSONObject pr = role.getJSONObject("projectRole");
  1525. if (pr == null || pr.isEmpty() || pr.isNullObject()) {
  1526. throw new GdcRestApiException("Can't extract role from JSON. No projectRole key in the JSON.");
  1527. }
  1528. JSONObject m = pr.getJSONObject("meta");
  1529. if (m == null || m.isEmpty() || m.isNullObject()) {
  1530. throw new GdcRestApiException("Can't extract role from JSON. No meta key in the JSON.");
  1531. }
  1532. JSONObject l = pr.getJSONObject("links");
  1533. if (l == null || l.isEmpty() || l.isNullObject()) {
  1534. throw new GdcRestApiException("Can't extract role from JSON. No links key in the JSON.");
  1535. }
  1536. String title = m.getString("title");
  1537. if (title == null || title.trim().length() <= 0) {
  1538. throw new GdcRestApiException("Can't extract user from JSON. No email key in the JSON.");
  1539. }
  1540. this.setName(title);
  1541. String u = l.getString("roleUsers");
  1542. if (u == null || u.trim().length() <= 0) {
  1543. throw new GdcRestApiException("Can't extract role from JSON. No roleUsers key in the JSON.");
  1544. }
  1545. this.setUri(u.replace(USERS_URI,""));
  1546. String i = m.getString("identifier");
  1547. if (i == null || i.trim().length() <= 0) {
  1548. throw new GdcRestApiException("Can't extract user from JSON. No email key in the JSON.");
  1549. }
  1550. this.setIdentifier(i);
  1551. }
  1552. public String getName() {
  1553. return name;
  1554. }
  1555. public void setName(String name) {
  1556. this.name = name;
  1557. }
  1558. public String getIdentifier() {
  1559. return identifier;
  1560. }
  1561. public void setIdentifier(String identifier) {
  1562. this.identifier = identifier;
  1563. }
  1564. public String getUri() {
  1565. return uri;
  1566. }
  1567. public void setUri(String uri) {
  1568. this.uri = uri;
  1569. }
  1570. public boolean validate() {
  1571. if (getName() != null && getIdentifier().length() > 0 && getUri() != null) // email is not mandatory
  1572. return true;
  1573. return false;
  1574. }
  1575. }
  1576. public static class GdcUser {
  1577. private String login;
  1578. private String email;
  1579. private String licence;
  1580. private String firstName;
  1581. private String lastName;
  1582. private String companyName;
  1583. private String position;
  1584. private String timezone;
  1585. private String country;
  1586. private String phoneNumber;
  1587. private String password;
  1588. private String verifyPassword;
  1589. private String ssoProvider;
  1590. private String status;
  1591. private String uri;
  1592. public GdcUser() {
  1593. }
  1594. public GdcUser(JSONObject user) {
  1595. if (user == null || user.isEmpty() || user.isNullObject()) {
  1596. throw new GdcRestApiException("Can't extract user from JSON. The JSON is empty.");
  1597. }
  1598. JSONObject u = user.getJSONObject("user");
  1599. if (u == null || u.isEmpty() || u.isNullObject()) {
  1600. throw new GdcRestApiException("Can't extract user from JSON. No user key in the JSON.");
  1601. }
  1602. JSONObject c = u.getJSONObject("content");
  1603. if (c == null || c.isEmpty() || c.isNullObject()) {
  1604. throw new GdcRestApiException("Can't extract user from JSON. No content key in the JSON.");
  1605. }
  1606. String v = c.getString("email");
  1607. if (v == null || v.trim().length() <= 0) {
  1608. throw new GdcRestApiException("Can't extract user from JSON. No email key in the JSON.");
  1609. }
  1610. this.setLogin(v);
  1611. v = c.getString("firstname");
  1612. if (v != null && v.trim().length() > 0) {
  1613. this.setFirstName(v);
  1614. }
  1615. v = c.getString("lastname");
  1616. if (v != null && v.trim().length() > 0) {
  1617. this.setLastName(v);
  1618. }
  1619. v = c.getString("email");
  1620. if (v != null && v.trim().length() > 0) {
  1621. this.setEmail(v);
  1622. }
  1623. v = c.getString("phonenumber");
  1624. if (v != null && v.trim().length() > 0) {
  1625. this.setPhoneNumber(v);
  1626. }
  1627. v = c.getString("status");
  1628. if (v != null && v.trim().length() > 0) {
  1629. this.setStatus(v);
  1630. }
  1631. JSONObject l = u.getJSONObject("links");
  1632. if (l == null || l.isEmpty() || l.isNullObject()) {
  1633. throw new GdcRestApiException("Can't extract user from JSON. No links key in the JSON.");
  1634. }
  1635. v = l.getString("self");
  1636. if (v == null || v.trim().length() <= 0) {
  1637. throw new GdcRestApiException("Can't extract user from JSON. No self key in the JSON.");
  1638. }
  1639. this.setUri(v);
  1640. }
  1641. public boolean validate() {
  1642. if (getLogin() != null && getLogin().length() > 0 && getPassword() != null
  1643. && getPassword().length() > 0 && getVerifyPassword() != null
  1644. && getVerifyPassword().length() > 0 && getFirstName() != null
  1645. && getFirstName().length() > 0 && getLastName() != null
  1646. && getLastName().length() > 0) // email is not mandatory
  1647. return true;
  1648. return false;
  1649. }
  1650. public String getLogin() {
  1651. return login;
  1652. }
  1653. public void setLogin(String login) {
  1654. this.login = login;
  1655. }
  1656. public String getUri() {
  1657. return uri;
  1658. }
  1659. public void setUri(String u) {
  1660. this.uri = u;
  1661. }
  1662. public String getStatus() {
  1663. return status;
  1664. }
  1665. public void setStatus(String s) {
  1666. this.status = s;
  1667. }
  1668. public String getLicence() {
  1669. return licence;
  1670. }
  1671. public void setLicence(String licence) {
  1672. this.licence = licence;
  1673. }
  1674. public String getFirstName() {
  1675. return firstName;
  1676. }
  1677. public void setFirstName(String firstName) {
  1678. this.firstName = firstName;
  1679. }
  1680. public String getLastName() {
  1681. return lastName;
  1682. }
  1683. public void setLastName(String lastName) {
  1684. this.lastName = lastName;
  1685. }
  1686. public String getCompanyName() {
  1687. return companyName;
  1688. }
  1689. public void setCompanyName(String companyName) {
  1690. this.companyName = companyName;
  1691. }
  1692. public String getPosition() {
  1693. return position;
  1694. }
  1695. public void setPosition(String position) {
  1696. this.position = position;
  1697. }
  1698. public String getTimezone() {
  1699. return timezone;
  1700. }
  1701. public void setTimezone(String timezone) {
  1702. this.timezone = timezone;
  1703. }
  1704. public String getCountry() {
  1705. return country;
  1706. }
  1707. public void setCountry(String country) {
  1708. this.country = country;
  1709. }
  1710. public String getPhoneNumber() {
  1711. return phoneNumber;
  1712. }
  1713. public void setPhoneNumber(String phoneNumber) {
  1714. this.phoneNumber = phoneNumber;
  1715. }
  1716. public String getPassword() {
  1717. return password;
  1718. }
  1719. public void setPassword(String password) {
  1720. this.password = password;
  1721. }
  1722. public String getVerifyPassword() {
  1723. return verifyPassword;
  1724. }
  1725. public void setVerifyPassword(String verifyPassword) {
  1726. this.verifyPassword = verifyPassword;
  1727. }
  1728. public String getSsoProvider() {
  1729. return ssoProvider;
  1730. }
  1731. public void setSsoProvider(String ssoProvider) {
  1732. this.ssoProvider = ssoProvider;
  1733. }
  1734. public String getEmail() {
  1735. return email;
  1736. }
  1737. public void setEmail(String email) {
  1738. this.email = email;
  1739. }
  1740. @Override
  1741. public String toString() {
  1742. return "DWGdcUser [getLogin()=" + getLogin() + ", getUri()=" + getUri() + ", getStatus()=" + getStatus()
  1743. + ", getLicence()=" + getLicence() + ", getFirstName()=" + getFirstName() + ", getLastName()="
  1744. + getLastName() + ", getCompanyName()=" + getCompanyName() + ", getPosition()=" + getPosition()
  1745. + ", getTimezone()=" + getTimezone() + ", getCountry()=" + getCountry() + ", getPhoneNumber()="
  1746. + getPhoneNumber() + ", getPassword()=" + getPassword() + ", getVerifyPassword()="
  1747. + getVerifyPassword() + ", getEmail()=" + getEmail() + "," + " getSsoProvider()=" + getSsoProvider() + "]";
  1748. }
  1749. }
  1750. /**
  1751. * Create a new user
  1752. *
  1753. * @param domain the domain where the user is going to be created
  1754. * @param user new user data
  1755. * @return the new user's URI
  1756. * @throws GdcRestApiException
  1757. */
  1758. public String createUser(String domain, GdcUser user)
  1759. throws GdcRestApiException {
  1760. if (user != null && user.validate()) {
  1761. l.debug("Creating new user " + user.getLogin() + " in domain " + domain);
  1762. PostMethod req = createPostMethod(getServerUrl() + DOMAIN_URI + "/" + domain + DOMAIN_USERS_SUFFIX);
  1763. JSONObject param = getCreateUserStructure(user);
  1764. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(
  1765. param.toString().getBytes()));
  1766. req.setRequestEntity(request);
  1767. String result = null;
  1768. try {
  1769. String response = executeMethodOk(req);
  1770. JSONObject responseObject = JSONObject.fromObject(response);
  1771. result = responseObject.getString("uri");
  1772. return result;
  1773. } catch (HttpMethodException ex) {
  1774. l.debug("Error creating user ", ex);
  1775. throw new GdcRestApiException("Error creating user ", ex);
  1776. } finally {
  1777. req.releaseConnection();
  1778. }
  1779. } else {
  1780. throw new InvalidParameterException("The new user must contain valid login, firstName, lastName, and password fields.");
  1781. }
  1782. }
  1783. private JSONObject getCreateUserStructure(GdcUser user) {
  1784. JSONObject param = new JSONObject();
  1785. JSONObject accountSetting = new JSONObject();
  1786. accountSetting.put("login", user.getLogin());
  1787. accountSetting.put("password", user.getPassword());
  1788. accountSetting.put("verifyPassword", user.getVerifyPassword());
  1789. accountSetting.put("firstName", user.getFirstName());
  1790. accountSetting.put("lastName", user.getLastName());
  1791. if (user.getCompanyName() != null && user.getCompanyName().length() > 0)
  1792. accountSetting.put("companyName", user.getCompanyName());
  1793. if (user.getPosition() != null && user.getPosition().length() > 0)
  1794. accountSetting.put("position", user.getPosition());
  1795. if (user.getCountry() != null && user.getCountry().length() > 0)
  1796. accountSetting.put("country", user.getCountry());
  1797. if (user.getTimezone() != null && user.getTimezone().length() > 0)
  1798. accountSetting.put("timezone", user.getTimezone());
  1799. else
  1800. accountSetting.put("timezone", null);
  1801. if (user.getPhoneNumber() != null && user.getPhoneNumber().length() > 0)
  1802. accountSetting.put("phoneNumber", user.getPhoneNumber());
  1803. if (user.getSsoProvider() != null && user.getSsoProvider().length() > 0)
  1804. accountSetting.put("ssoProvider", user.getSsoProvider());
  1805. if (user.getEmail() != null && user.getEmail().length() > 0)
  1806. accountSetting.put("email", user.getEmail());
  1807. param.put("accountSetting", accountSetting);
  1808. return param;
  1809. }
  1810. private String getRoleUri(String projectId, String role) {
  1811. String roleUri = null;
  1812. // for backward compatibility
  1813. if(ROLES.containsKey(role.toUpperCase())) {
  1814. role = ROLES.get(role.toUpperCase());
  1815. }
  1816. List<GdcRole> roles = getProjectRoles(projectId);
  1817. for(GdcRole r : roles) {
  1818. String identifier = r.getIdentifier();
  1819. if(identifier.equalsIgnoreCase(role)) {
  1820. roleUri = r.getUri();
  1821. }
  1822. }
  1823. return roleUri;
  1824. }
  1825. /**
  1826. * Create a new user
  1827. *
  1828. * @param projectId project ID
  1829. * @param uris user URIs
  1830. * @param role user's role
  1831. * @return the new user's URI
  1832. * @throws GdcRestApiException
  1833. */
  1834. public void addUsersToProject(String projectId, List<String> uris, String role)
  1835. throws GdcRestApiException {
  1836. l.debug("Adding users " + uris + " to project " + projectId + " in role "+ role);
  1837. String projectsUrl = getProjectUrl(projectId);
  1838. String roleUri = getRoleUri(projectId, role);
  1839. addUsersToProjectWithRoleUri(projectId, uris, roleUri);
  1840. }
  1841. public void addUsersToProjectWithRoleUri(String projectId, List<String> uris, String roleUri)
  1842. throws GdcRestApiException {
  1843. l.debug("Adding users " + uris + " to project " + projectId + " with roleUri "+ roleUri);
  1844. String projectsUrl = getProjectUrl(projectId);
  1845. PostMethod req = createPostMethod(projectsUrl + PROJECT_USERS_SUFFIX);
  1846. JSONObject param = getAddUsersToProjectStructure(uris, roleUri);
  1847. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(
  1848. param.toString().getBytes()));
  1849. req.setRequestEntity(request);
  1850. String result = null;
  1851. try {
  1852. String response = executeMethodOk(req);
  1853. JSONObject responseObject = JSONObject.fromObject(response);
  1854. JSONObject projectUsersUpdateResult = responseObject.getJSONObject("projectUsersUpdateResult");
  1855. JSONArray failed = projectUsersUpdateResult.getJSONArray("failed");
  1856. if (!failed.isEmpty()) {
  1857. String errMsg = "Following users can't be added to the project:";
  1858. for (Object uri : failed.toArray()) {
  1859. errMsg += " " + uris.toString();
  1860. }
  1861. l.debug(errMsg);
  1862. throw new GdcRestApiException(errMsg);
  1863. }
  1864. //JSONArray successful = projectUsersUpdateResult.getJSONArray("successful");
  1865. } catch (HttpMethodException ex) {
  1866. l.debug("Error adding users " + uris + " to project", ex);
  1867. throw new GdcRestApiException("Error adding users " + uris + " to project ", ex);
  1868. } finally {
  1869. req.releaseConnection();
  1870. }
  1871. }
  1872. private JSONObject getAddUsersToProjectStructure(List<String> uris, String roleUri) {
  1873. JSONObject param = new JSONObject();
  1874. JSONArray users = new JSONArray();
  1875. JSONArray roles = null;
  1876. if (roleUri != null && roleUri.trim().length() > 0) {
  1877. roles = new JSONArray();
  1878. roles.add(roleUri);
  1879. }
  1880. for (String uri : uris) {
  1881. JSONObject user = new JSONObject();
  1882. JSONObject content = new JSONObject();
  1883. if (roles != null)
  1884. content.put("userRoles", roles);
  1885. content.put("status", "ENABLED");
  1886. user.put("content", content);
  1887. JSONObject links = new JSONObject();
  1888. links.put("self", uri);
  1889. user.put("links", links);
  1890. JSONObject item = new JSONObject();
  1891. item.put("user", user);
  1892. users.add(item);
  1893. }
  1894. param.put("users", users);
  1895. return param;
  1896. }
  1897. /**
  1898. * Disables a user in project
  1899. *
  1900. * @param projectId project ID
  1901. * @param uris user URIs
  1902. * @throws GdcRestApiException
  1903. */
  1904. public void disableUsersInProject(String projectId, List<String> uris)
  1905. throws GdcRestApiException {
  1906. l.debug("Disabling users " + uris + " in project " + projectId);
  1907. String projectsUrl = getProjectUrl(projectId);
  1908. PostMethod req = createPostMethod(projectsUrl + PROJECT_USERS_SUFFIX);
  1909. JSONObject param = getDisableUsersInProjectStructure(uris);
  1910. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(
  1911. param.toString().getBytes()));
  1912. req.setRequestEntity(request);
  1913. String result = null;
  1914. try {
  1915. String response = executeMethodOk(req);
  1916. JSONObject responseObject = JSONObject.fromObject(response);
  1917. JSONObject projectUsersUpdateResult = responseObject.getJSONObject("projectUsersUpdateResult");
  1918. JSONArray failed = projectUsersUpdateResult.getJSONArray("failed");
  1919. if (!failed.isEmpty()) {
  1920. String errMsg = "Following users can't be disabled in the project:";
  1921. for (Object uri : failed.toArray()) {
  1922. errMsg += " " + uris.toString();
  1923. }
  1924. l.debug(errMsg);
  1925. throw new GdcRestApiException(errMsg);
  1926. }
  1927. //JSONArray successful = projectUsersUpdateResult.getJSONArray("successful");
  1928. } catch (HttpMethodException ex) {
  1929. l.debug("Error disabling users " + uris + " in project", ex);
  1930. throw new GdcRestApiException("Error disabling users " + uris + " in project ", ex);
  1931. } finally {
  1932. req.releaseConnection();
  1933. }
  1934. }
  1935. private JSONObject getDisableUsersInProjectStructure(List<String> uris) {
  1936. JSONObject param = new JSONObject();
  1937. JSONArray users = new JSONArray();
  1938. for (String uri : uris) {
  1939. JSONObject user = new JSONObject();
  1940. JSONObject content = new JSONObject();
  1941. content.put("status", "DISABLED");
  1942. user.put("content", content);
  1943. JSONObject links = new JSONObject();
  1944. links.put("self", uri);
  1945. user.put("links", links);
  1946. JSONObject item = new JSONObject();
  1947. item.put("user", user);
  1948. users.add(item);
  1949. }
  1950. param.put("users", users);
  1951. return param;
  1952. }
  1953. /**
  1954. * Returns the selected project's roles
  1955. *
  1956. * @param pid project ID
  1957. * @return array of the project's users
  1958. */
  1959. public ArrayList<GdcRole> getProjectRoles(String pid) {
  1960. ArrayList<GdcRole> ret = new ArrayList<GdcRole>();
  1961. l.debug("Executing getProjectRoles for project id=" + pid);
  1962. HttpMethod req = createGetMethod(getProjectUrl(pid) + ROLES_URI);
  1963. try {
  1964. String resp = executeMethodOk(req);
  1965. JSONObject parsedResp = JSONObject.fromObject(resp);
  1966. if (parsedResp == null || parsedResp.isNullObject() || parsedResp.isEmpty()) {
  1967. l.debug("Can't getProjectRoles for project id=" + pid + ". Invalid response.");
  1968. throw new GdcRestApiException("Can't getProjectRoles for project id=" + pid + ". Invalid response.");
  1969. }
  1970. JSONObject projectRoles = parsedResp.getJSONObject("projectRoles");
  1971. if (projectRoles == null || projectRoles.isNullObject() || projectRoles.isEmpty()) {
  1972. l.debug("Can't getProjectRoles for project id=" + pid + ". No projectRoles key in the response.");
  1973. throw new GdcRestApiException("Can't getProjectRoles for project id=" + pid + ". No projectRoles key in the response.");
  1974. }
  1975. JSONArray roles = projectRoles.getJSONArray("roles");
  1976. if (roles == null) {
  1977. l.debug("Can't getRoleUsers. No getProjectRoles key in the response.");
  1978. throw new GdcRestApiException("Can't getProjectRoles. No roles key in the response.");
  1979. }
  1980. for (Object o : roles) {
  1981. String role = (String) o;
  1982. GdcRole g = getRoleFromUri(role);
  1983. ret.add(g);
  1984. }
  1985. return ret;
  1986. } finally {
  1987. req.releaseConnection();
  1988. }
  1989. }
  1990. /**
  1991. * Returns the selected project's roles
  1992. *
  1993. * @return array of the project's users
  1994. */
  1995. public ArrayList<String> getRoleUsers(GdcRole role, boolean activeUsersOnly) {
  1996. ArrayList<String> ret = new ArrayList<String>();
  1997. if(role == null || role.getIdentifier() == null || role.getIdentifier().length() == 0 || role.getUri() == null
  1998. || role.getUri().length() == 0 || role.getName() == null || role.getName().length() == 0) {
  1999. l.debug("Can't getRoleUsers . Invalid role object passed.");
  2000. throw new GdcRestApiException("Can't getRoleUsers. Invalid role object passed.");
  2001. }
  2002. l.debug("Executing getRoleUsers for role "+role.getIdentifier());
  2003. HttpMethod req = createGetMethod(getServerUrl() + role.getUri() + USERS_URI);
  2004. try {
  2005. String resp = executeMethodOk(req);
  2006. JSONObject parsedResp = JSONObject.fromObject(resp);
  2007. if (parsedResp == null || parsedResp.isNullObject() || parsedResp.isEmpty()) {
  2008. l.debug("Can't getRoleUsers. Invalid response.");
  2009. throw new GdcRestApiException("Can't getRoleUsers. Invalid response.");
  2010. }
  2011. JSONObject associatedUsers = parsedResp.getJSONObject("associatedUsers");
  2012. if (associatedUsers == null || associatedUsers.isNullObject() || associatedUsers.isEmpty()) {
  2013. l.debug("Can't getRoleUsers. Invalid response. No associatedUsers key.");
  2014. throw new GdcRestApiException("Can't getRoleUsers. Invalid response. No associatedUsers key.");
  2015. }
  2016. JSONArray users = associatedUsers.getJSONArray("users");
  2017. if (users == null) {
  2018. l.debug("Can't getRoleUsers. No users key in the response.");
  2019. throw new GdcRestApiException("Can't getRoleUsers. No users key in the response.");
  2020. }
  2021. for (Object o : users) {
  2022. String user = (String) o;
  2023. ret.add(user);
  2024. }
  2025. return ret;
  2026. } finally {
  2027. req.releaseConnection();
  2028. }
  2029. }
  2030. /**
  2031. * Returns the selected project's users
  2032. *
  2033. * @param pid project ID
  2034. * @param activeUsersOnly lists only active users
  2035. * @return array of the project's users
  2036. */
  2037. public ArrayList<GdcUser> getProjectUsers(String pid, boolean activeUsersOnly) {
  2038. ArrayList<GdcUser> ret = new ArrayList<GdcUser>();
  2039. l.debug("Executing getProjectUsers for project id=" + pid);
  2040. HttpMethod req = createGetMethod(getProjectUrl(pid) + PROJECT_USERS_SUFFIX);
  2041. try {
  2042. String resp = executeMethodOk(req);
  2043. JSONObject parsedResp = JSONObject.fromObject(resp);
  2044. if (parsedResp == null || parsedResp.isNullObject() || parsedResp.isEmpty()) {
  2045. l.debug("Can't getProjectUsers for project id=" + pid + ". Invalid response.");
  2046. throw new GdcRestApiException("Can't getProjectUsers for project id=" + pid + ". Invalid response.");
  2047. }
  2048. JSONArray users = parsedResp.getJSONArray("users");
  2049. if (users == null) {
  2050. l.debug("Can't getProjectUsers for project id=" + pid + ". No users key in the response.");
  2051. throw new GdcRestApiException("Can't getProjectUsers for project id=" + pid + ". No users key in the response.");
  2052. }
  2053. for (Object o : users) {
  2054. JSONObject user = (JSONObject) o;
  2055. GdcUser g = new GdcUser(user);
  2056. if ((activeUsersOnly && "ENABLED".equalsIgnoreCase(g.getStatus())) || (!activeUsersOnly)) {
  2057. ret.add(g);
  2058. }
  2059. }
  2060. return ret;
  2061. } finally {
  2062. req.releaseConnection();
  2063. }
  2064. }
  2065. /**
  2066. * Imports the project
  2067. *
  2068. * @param projectId the project's ID
  2069. * @param token export token
  2070. * @return result the taskUri
  2071. * @throws GdcRestApiException
  2072. */
  2073. public String importProject(String projectId, String token)
  2074. throws GdcRestApiException {
  2075. l.debug("Importing project projectId=" + projectId + " token:" + token);
  2076. PostMethod req = createPostMethod(getProjectMdUrl(projectId) + PROJECT_IMPORT_URI);
  2077. JSONObject param = getImportProjectStructure(token);
  2078. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(
  2079. param.toString().getBytes()));
  2080. req.setRequestEntity(request);
  2081. String result = null;
  2082. try {
  2083. String response = executeMethodOk(req);
  2084. JSONObject responseObject = JSONObject.fromObject(response);
  2085. result = responseObject.getString("uri");
  2086. return result;
  2087. } catch (HttpMethodException ex) {
  2088. l.debug("Error importing project", ex);
  2089. throw new GdcRestApiException("Error importing project", ex);
  2090. } finally {
  2091. req.releaseConnection();
  2092. }
  2093. }
  2094. private JSONObject getImportProjectStructure(String token) {
  2095. JSONObject param = new JSONObject();
  2096. JSONObject importProject = new JSONObject();
  2097. importProject.put("token", token);
  2098. param.put("importProject", importProject);
  2099. return param;
  2100. }
  2101. /**
  2102. * Imports a MD object to the project
  2103. *
  2104. * @param projectId the project's ID
  2105. * @param token export token
  2106. * @param overwrite overwrite existing objects
  2107. * @param updateLDM update LDM names, descriptions and tags
  2108. * @return result the taskUri
  2109. * @throws GdcRestApiException
  2110. */
  2111. public String importMD(String projectId, String token, boolean overwrite, boolean updateLDM)
  2112. throws GdcRestApiException {
  2113. l.debug("Importing metadata objects for projectId=" + projectId + " token:" + token);
  2114. PostMethod req = createPostMethod(getProjectMdUrl(projectId) + PROJECT_PARTIAL_IMPORT_URI);
  2115. JSONObject param = getMDImportStructure(token, overwrite, updateLDM);
  2116. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(
  2117. param.toString().getBytes()));
  2118. req.setRequestEntity(request);
  2119. String result = null;
  2120. try {
  2121. String response = executeMethodOk(req);
  2122. JSONObject responseObject = JSONObject.fromObject(response);
  2123. result = responseObject.getString("uri");
  2124. return result;
  2125. } catch (HttpMethodException ex) {
  2126. l.debug("Error importing metadata objects for projectId=" + projectId + " token:" + token, ex);
  2127. throw new GdcRestApiException("Error importing metadata objects for projectId=" + projectId + " token:" + token, ex);
  2128. } finally {
  2129. req.releaseConnection();
  2130. }
  2131. }
  2132. private JSONObject getMDImportStructure(String token, boolean overwrite, boolean updateLDM) {
  2133. JSONObject param = new JSONObject();
  2134. JSONObject importMD = new JSONObject();
  2135. importMD.put("token", token);
  2136. importMD.put("overwriteNewer", (overwrite) ? (1) : (0));
  2137. importMD.put("updateLDMObjects", (updateLDM) ? (1) : (0));
  2138. param.put("partialMDImport", importMD);
  2139. return param;
  2140. }
  2141. /**
  2142. * Exports selected MD object with dependencies from the project
  2143. *
  2144. * @param projectId the project's ID
  2145. * @param ids - list of the exported MD objects IDs
  2146. * @return result the taskUri and the export token
  2147. * @throws GdcRestApiException
  2148. */
  2149. public ProjectExportResult exportMD(String projectId, List<Integer> ids)
  2150. throws GdcRestApiException {
  2151. l.debug("Exporting metadata objects with IDs " + ids + " from project " + projectId);
  2152. PostMethod req = createPostMethod(getProjectMdUrl(projectId) + PROJECT_PARTIAL_EXPORT_URI);
  2153. JSONObject param = getMDExportStructure(projectId, ids);
  2154. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(
  2155. param.toString().getBytes()));
  2156. req.setRequestEntity(request);
  2157. ProjectExportResult result = null;
  2158. try {
  2159. String response = executeMethodOk(req);
  2160. result = new ProjectExportResult();
  2161. JSONObject responseObject = JSONObject.fromObject(response);
  2162. JSONObject exportArtifact = responseObject.getJSONObject("partialMDArtifact");
  2163. JSONObject status = exportArtifact.getJSONObject("status");
  2164. result.setTaskUri(status.getString("uri"));
  2165. result.setExportToken(exportArtifact.getString("token"));
  2166. return result;
  2167. } catch (HttpMethodException ex) {
  2168. l.debug("Error exporting metadata objects with IDs " + ids + " from project " + projectId, ex);
  2169. throw new GdcRestApiException("Error exporting metadata objects with IDs " + ids + " from project " + projectId, ex);
  2170. } finally {
  2171. req.releaseConnection();
  2172. }
  2173. }
  2174. private JSONObject getMDExportStructure(String projectId, List<Integer> ids) {
  2175. JSONObject param = new JSONObject();
  2176. String puri = "/gdc/md/" + projectId;
  2177. JSONObject partialMDExport = new JSONObject();
  2178. JSONArray uris = new JSONArray();
  2179. for (Integer id : ids) {
  2180. uris.add(puri + "/obj/" + id);
  2181. }
  2182. partialMDExport.put("uris", uris);
  2183. param.put("partialMDExport", partialMDExport);
  2184. return param;
  2185. }
  2186. /**
  2187. * Checks if the migration is finished
  2188. *
  2189. * @param link the link returned from the start loading
  2190. * @return the loading status
  2191. */
  2192. public String getMigrationStatus(String link) throws HttpMethodException {
  2193. l.debug("Getting project migration status uri=" + link);
  2194. HttpMethod ptm = createGetMethod(getServerUrl() + link);
  2195. try {
  2196. String response = executeMethodOk(ptm);
  2197. JSONObject task = JSONObject.fromObject(response);
  2198. JSONObject state = task.getJSONObject("taskState");
  2199. if (state != null && !state.isNullObject() && !state.isEmpty()) {
  2200. String status = state.getString("status");
  2201. l.debug("Migration status=" + status);
  2202. return status;
  2203. } else {
  2204. l.debug("No taskState structure in the migration status!");
  2205. throw new GdcRestApiException("No taskState structure in the migration status!");
  2206. }
  2207. } finally {
  2208. ptm.releaseConnection();
  2209. }
  2210. }
  2211. /**
  2212. * Executes the MAQL and creates/modifies the project's LDM
  2213. *
  2214. * @param projectId the project's ID
  2215. * @param maql String with the MAQL statements
  2216. * @return result String
  2217. * @throws GdcRestApiException
  2218. */
  2219. public String executeDML(String projectId, String maql) throws GdcRestApiException {
  2220. l.debug("Executing MAQL DML projectId=" + projectId + " MAQL DML:\n" + maql);
  2221. PostMethod maqlPost = createPostMethod(getProjectMdUrl(projectId) + DML_EXEC_URI);
  2222. JSONObject maqlStructure = getMAQLExecStructure(maql);
  2223. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(
  2224. maqlStructure.toString().getBytes()));
  2225. maqlPost.setRequestEntity(request);
  2226. String result = null;
  2227. try {
  2228. String response = executeMethodOk(maqlPost);
  2229. JSONObject responseObject = JSONObject.fromObject(response);
  2230. String uris = responseObject.getString("uri");
  2231. return uris;
  2232. } catch (HttpMethodException ex) {
  2233. l.debug("MAQL DML execution: ", ex);
  2234. throw new GdcRestApiException("MAQL DML execution: ", ex);
  2235. } finally {
  2236. maqlPost.releaseConnection();
  2237. }
  2238. }
  2239. /**
  2240. * Returns the pull API JSON structure
  2241. *
  2242. * @param maql String with the MAQL statements
  2243. * @return the MAQL API JSON structure
  2244. */
  2245. private JSONObject getMAQLExecStructure(String maql) {
  2246. JSONObject maqlStructure = new JSONObject();
  2247. JSONObject maqlObj = new JSONObject();
  2248. maqlObj.put("maql", maql);
  2249. maqlStructure.put("manage", maqlObj);
  2250. return maqlStructure;
  2251. }
  2252. protected String executeMethodOk(HttpMethod method) throws HttpMethodException {
  2253. return executeMethodOk(method, true);
  2254. }
  2255. protected String executeMethodOk(HttpMethod method, boolean reloginOn401) throws HttpMethodException {
  2256. return executeMethodOk(method, reloginOn401, 16);
  2257. }
  2258. /**
  2259. * Executes HttpMethod and test if the response if 200(OK)
  2260. *
  2261. * @param method the HTTP method
  2262. * @return response body as String
  2263. * @throws HttpMethodException
  2264. */
  2265. private String executeMethodOk(HttpMethod method, boolean reloginOn401, int retries) throws HttpMethodException {
  2266. try {
  2267. executeMethodOkOnly(method, reloginOn401, retries);
  2268. return method.getResponseBodyAsString();
  2269. } catch (IOException e) {
  2270. l.debug("Error invoking GoodData REST API.", e);
  2271. throw new HttpMethodException("Error invoking GoodData REST API.", e);
  2272. }
  2273. }
  2274. private void executeMethodOkOnly(HttpMethod method) throws HttpMethodException {
  2275. executeMethodOkOnly(method, true);
  2276. }
  2277. private void executeMethodOkOnly(HttpMethod method, boolean reloginOn401) throws HttpMethodException {
  2278. executeMethodOk(method, reloginOn401, 16);
  2279. }
  2280. /**
  2281. * Executes HttpMethod and test if the response if 200(OK)
  2282. *
  2283. * @param method the HTTP method
  2284. * @return response as Stream
  2285. * @throws HttpMethodException
  2286. */
  2287. private void executeMethodOkOnly(HttpMethod method, boolean reloginOn401, int retries) throws HttpMethodException, IOException {
  2288. try {
  2289. client.executeMethod(method);
  2290. /* HttpClient is rather unsupportive when it comes to robust interpreting
  2291. * of response classes; which is mandated by RFC and extensively used in
  2292. * GoodData API. Let us grok the classes ourselves. */
  2293. /* 2xx success class */
  2294. if (method.getStatusCode() == HttpStatus.SC_CREATED) {
  2295. return;
  2296. } else if (method.getStatusCode() == HttpStatus.SC_ACCEPTED) {
  2297. throw new HttpMethodNotFinishedYetException(method.getResponseBodyAsString());
  2298. } else if (method.getStatusCode() == HttpStatus.SC_NO_CONTENT) {
  2299. return;
  2300. } else if (method.getStatusCode() >= HttpStatus.SC_OK
  2301. && method.getStatusCode() < HttpStatus.SC_BAD_REQUEST) {
  2302. return;
  2303. /* 4xx user errors and
  2304. * 5xx backend trouble */
  2305. } else if (method.getStatusCode() == HttpStatus.SC_UNAUTHORIZED && reloginOn401) {
  2306. // refresh the temporary token
  2307. setTokenCookie();
  2308. executeMethodOkOnly(method, false, retries);
  2309. return;
  2310. } else if (method.getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE && retries-- > 0
  2311. && method.getResponseHeader("Retry-After") != null) {
  2312. /* This is recommended by RFC 2616 and should probably be dealt with by the
  2313. * client library. May god have mercy with it. */
  2314. int timeout = Integer.parseInt(method.getResponseHeader("Retry-After").getValue());
  2315. l.debug("Remote asked us to retry after " + timeout + " seconds, sleeping.");
  2316. l.debug(retries + " more retries");
  2317. try {
  2318. Thread.currentThread().sleep(Constants.RETRY_INTERVAL * timeout);
  2319. } catch (java.lang.InterruptedException e) {
  2320. }
  2321. executeMethodOkOnly(method, false, retries);
  2322. return;
  2323. } else if (method.getStatusCode() == HttpStatus.SC_GONE) {
  2324. throw new GdcProjectAccessException("Invalid project.");
  2325. } else if (method.getStatusCode() >= HttpStatus.SC_BAD_REQUEST
  2326. && method.getStatusCode() < 600) {
  2327. throw new HttpMethodException(method);
  2328. /* 1xx informational responses class and
  2329. * 3xx redirects should not get past the client library internals. */
  2330. } else {
  2331. throw new HttpMethodException("Unsupported HTTP status received from remote: " +
  2332. method.getStatusCode());
  2333. }
  2334. } catch (HttpException e) {
  2335. l.debug("Error invoking GoodData REST API.", e);
  2336. throw new HttpMethodException("Error invoking GoodData REST API.", e);
  2337. }
  2338. }
  2339. /**
  2340. * Returns the data interfaces URI
  2341. *
  2342. * @param projectId project ID
  2343. * @return SLI collection URI
  2344. */
  2345. public String getSLIsUri(String projectId) {
  2346. return getProjectMdUrl(projectId) + DATA_INTERFACES_URI;
  2347. }
  2348. /**
  2349. * Returns the SLI URI
  2350. *
  2351. * @param sliId SLI ID
  2352. * @param projectId project ID
  2353. * @return DLI URI
  2354. */
  2355. public String getSLIUri(String sliId, String projectId) {
  2356. return getProjectMdUrl(projectId) + DATA_INTERFACES_URI + "/" + sliId + SLI_DESCRIPTOR_URI;
  2357. }
  2358. protected String getServerUrl() {
  2359. return config.getUrl();
  2360. }
  2361. /**
  2362. * Constructs project's metadata uri
  2363. *
  2364. * @param projectId project ID
  2365. */
  2366. protected String getProjectMdUrl(String projectId) {
  2367. return getServerUrl() + MD_URI + projectId;
  2368. }
  2369. /**
  2370. * Constructs project's projects uri
  2371. *
  2372. * @param projectId project ID
  2373. */
  2374. protected String getProjectUrl(String projectId) {
  2375. return getServerUrl() + PROJECTS_URI + "/" + projectId;
  2376. }
  2377. /**
  2378. * Gets the project ID from the project URI
  2379. *
  2380. * @param projectUri project URI
  2381. * @return the project id
  2382. */
  2383. public String getProjectIdFromUri(String projectUri) {
  2384. String[] cmpnts = projectUri.split("/");
  2385. if (cmpnts != null && cmpnts.length > 0) {
  2386. String id = cmpnts[cmpnts.length - 1];
  2387. return id;
  2388. } else
  2389. throw new GdcRestApiException("Invalid project uri structure uri=" + projectUri);
  2390. }
  2391. /**
  2392. * Gets the project delete URI from the project id
  2393. *
  2394. * @param projectId project ID
  2395. * @return the project delete URI
  2396. */
  2397. public String getProjectDeleteUri(String projectId) {
  2398. return PROJECTS_URI + "/" + projectId;
  2399. }
  2400. /**
  2401. * Profile getter
  2402. *
  2403. * @return the profile of the currently logged user
  2404. */
  2405. protected JSONObject getProfile() {
  2406. return profile;
  2407. }
  2408. /**
  2409. * Invites a new user to a project
  2410. *
  2411. * @param projectId project ID
  2412. * @param eMail invited user e-mail
  2413. * @param message invitation message
  2414. */
  2415. public void inviteUser(String projectId, String eMail, String message) {
  2416. this.inviteUser(projectId, eMail, message, null);
  2417. }
  2418. /**
  2419. * Invites a new user to a project
  2420. *
  2421. * @param projectId project ID
  2422. * @param eMail invited user e-mail
  2423. * @param message invitation message
  2424. */
  2425. public void inviteUser(String projectId, String eMail, String message, String role) {
  2426. l.debug("Executing inviteUser projectId=" + projectId + " e-mail=" + eMail + " message=" + message);
  2427. PostMethod invitePost = createPostMethod(getServerUrl() + getProjectDeleteUri(projectId) + INVITATION_URI);
  2428. JSONObject inviteStructure = getInviteStructure(projectId, eMail, message, role);
  2429. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(
  2430. inviteStructure.toString().getBytes()));
  2431. invitePost.setRequestEntity(request);
  2432. try {
  2433. executeMethodOk(invitePost);
  2434. } catch (HttpMethodException ex) {
  2435. l.debug("Failed executing inviteUser projectId=" + projectId + " e-mail=" + eMail + " message=" + message);
  2436. throw new GdcRestApiException("Failed executing inviteUser projectId=" + projectId + " e-mail=" + eMail + " message=" + message, ex);
  2437. } finally {
  2438. invitePost.releaseConnection();
  2439. }
  2440. }
  2441. /**
  2442. * Creates a new invitation structure
  2443. *
  2444. * @param pid project id
  2445. * @param eMail e-mail
  2446. * @param msg invitation message
  2447. * @return the new invitation structure
  2448. */
  2449. private JSONObject getInviteStructure(String pid, String eMail, String msg, String role) {
  2450. JSONObject content = new JSONObject();
  2451. content.put("firstname", "");
  2452. content.put("lastname", "");
  2453. content.put("email", eMail);
  2454. if (role != null && role.length() > 0) {
  2455. String roleUri = getRoleUri(pid, role);
  2456. if (roleUri == null)
  2457. throw new InvalidParameterException("The role '" + role + "' is not recognized by the GoodData platform.");
  2458. content.put("role", roleUri);
  2459. }
  2460. JSONObject action = new JSONObject();
  2461. action.put("setMessage", msg);
  2462. content.put("action", action);
  2463. JSONObject invitation = new JSONObject();
  2464. invitation.put("content", content);
  2465. JSONObject invitations = new JSONObject();
  2466. JSONArray ia = new JSONArray();
  2467. JSONObject inve = new JSONObject();
  2468. inve.put("invitation", invitation);
  2469. ia.add(inve);
  2470. invitations.put("invitations", ia);
  2471. return invitations;
  2472. }
  2473. /**
  2474. * Converst MD identifier to uri
  2475. *
  2476. * @param projectId project ID
  2477. * @param identifiers MD object identifiers
  2478. * @return map identifier:uri
  2479. */
  2480. public Map<String, String> identifierToUri(String projectId, String[] identifiers) {
  2481. l.debug("Executing identifierToUri identifier=" + identifiers);
  2482. Map<String, String> result = new HashMap<String, String>();
  2483. PostMethod p = createPostMethod(getProjectMdUrl(projectId) + IDENTIFIER_URI);
  2484. JSONObject is = getIdentifiersStructure(identifiers);
  2485. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(
  2486. is.toString().getBytes()));
  2487. p.setRequestEntity(request);
  2488. try {
  2489. String resp = executeMethodOk(p);
  2490. JSONObject parsedResp = JSONObject.fromObject(resp);
  2491. JSONArray idents = parsedResp.getJSONArray("identifiers");
  2492. if (idents != null && !idents.isEmpty()) {
  2493. for (int i = 0; i < idents.size(); i++) {
  2494. JSONObject ident = idents.getJSONObject(i);
  2495. result.put(ident.getString("identifier"), ident.getString("uri"));
  2496. }
  2497. }
  2498. } catch (HttpMethodException ex) {
  2499. l.debug("Failed executing identifierToUri identifier=" + identifiers);
  2500. throw new GdcRestApiException("Failed executing identifierToUri identifier=" + identifiers, ex);
  2501. } finally {
  2502. p.releaseConnection();
  2503. }
  2504. return result;
  2505. }
  2506. /**
  2507. * Creates a new identifiers structure
  2508. *
  2509. * @param identifiers MD object identifier
  2510. * @return the new identifiers structure
  2511. */
  2512. private JSONObject getIdentifiersStructure(String[] identifiers) {
  2513. JSONObject identifierToUri = new JSONObject();
  2514. JSONArray ids = new JSONArray();
  2515. for (int i = 0; i < identifiers.length; i++) {
  2516. ids.add(identifiers[i]);
  2517. }
  2518. identifierToUri.put("identifierToUri", ids);
  2519. return identifierToUri;
  2520. }
  2521. /**
  2522. * Retrieves a metadata object definition by Uri
  2523. *
  2524. * @param objectUri object uri
  2525. * @return the object to get
  2526. */
  2527. public JSONObject getObjectByUri(String objectUri) {
  2528. l.debug("Executing getObjectByUri uri=" + objectUri);
  2529. HttpMethod req = createGetMethod(getServerUrl() + objectUri);
  2530. try {
  2531. String resp = executeMethodOk(req);
  2532. // workaround for a possible mess in MAQL source and missing charset in /obj response
  2533. resp = resp.replace("\\\\_", " ").replace("\u00A0", " ");
  2534. JSONObject parsedResp = JSONObject.fromObject(resp);
  2535. if (parsedResp.isNullObject()) {
  2536. l.debug("Can't getObjectByUri object uri=" + objectUri);
  2537. throw new GdcRestApiException("Can't getObjectByUri object uri=" + objectUri);
  2538. }
  2539. return parsedResp;
  2540. } finally {
  2541. req.releaseConnection();
  2542. }
  2543. }
  2544. /**
  2545. * Retrieves a metadata object definition
  2546. *
  2547. * @param objectUri object uri
  2548. * @return the object to get
  2549. */
  2550. public MetadataObject getMetadataObject(String objectUri) {
  2551. l.debug("Executing getMetadataObject uri=" + objectUri);
  2552. MetadataObject o = new MetadataObject(getObjectByUri(objectUri));
  2553. return o;
  2554. }
  2555. /**
  2556. * Retrieves a metadata object definition
  2557. *
  2558. * @param projectId project id (hash)
  2559. * @param objectId object id (integer)
  2560. * @return the object to get
  2561. */
  2562. public MetadataObject getMetadataObject(String projectId, int objectId) {
  2563. l.debug("Executing getMetadataObject id=" + objectId + " on project id=" + projectId);
  2564. return getMetadataObject(MD_URI + projectId + OBJ_URI + "/" + objectId);
  2565. }
  2566. /**
  2567. * Retrieves a metadata object definition
  2568. *
  2569. * @param projectId project id (hash)
  2570. * @param identifier object identifier
  2571. * @return the object to get
  2572. */
  2573. public MetadataObject getMetadataObject(String projectId, String identifier) {
  2574. l.debug("Executing getObjectByIdentifier identifier=" + identifier);
  2575. Map<String, String> uris = identifierToUri(projectId, new String[]{identifier});
  2576. if (uris != null && uris.size() > 0) {
  2577. String uri = uris.get(identifier);
  2578. if (uri != null && uri.length() > 0)
  2579. return getMetadataObject(uri);
  2580. else {
  2581. l.debug("Can't getObjectByIdentifier identifier=" + identifier + " The identifier doesn't exists.");
  2582. throw new GdcRestApiException("Can't getObjectByIdentifier identifier=" + identifier + " The identifier doesn't exists.");
  2583. }
  2584. } else {
  2585. l.debug("Can't getObjectByIdentifier identifier=" + identifier + " The identifier doesn't exists.");
  2586. throw new GdcRestApiException("Can't getObjectByIdentifier identifier=" + identifier + " The identifier doesn't exists.");
  2587. }
  2588. }
  2589. /**
  2590. * Returns the dependent objects
  2591. *
  2592. * @param uri the uri of the top-level object
  2593. * @return list of dependent objects
  2594. */
  2595. public List<JSONObject> using(String uri) {
  2596. l.debug("Executing using uri=" + uri);
  2597. List<JSONObject> ret = new ArrayList<JSONObject>();
  2598. //HACK!
  2599. String usedUri = uri.replace("/obj/", "/using/");
  2600. HttpMethod req = createGetMethod(getServerUrl() + usedUri);
  2601. try {
  2602. String resp = executeMethodOk(req);
  2603. JSONObject parsedResp = JSONObject.fromObject(resp);
  2604. if (parsedResp == null || parsedResp.isNullObject() || parsedResp.isEmpty()) {
  2605. l.debug("Can't call using on uri=" + uri + ". Invalid response.");
  2606. throw new GdcRestApiException("Can't call using on uri=" + uri + ". Invalid response.");
  2607. }
  2608. JSONObject using = parsedResp.getJSONObject("using");
  2609. if (using == null || using.isNullObject() || using.isEmpty()) {
  2610. l.debug("Can't call using on uri=" + uri + ". No using data.");
  2611. throw new GdcRestApiException("Can't call using on uri=" + uri + ". No using data.");
  2612. }
  2613. JSONArray nodes = using.getJSONArray("nodes");
  2614. if (nodes == null) {
  2615. l.debug("Can't call using on uri=" + uri + ". No nodes key in the response.");
  2616. throw new GdcRestApiException("Can't call using on uri=" + uri + ". No nodes key in the response.");
  2617. }
  2618. for (Object o : nodes) {
  2619. JSONObject obj = (JSONObject) o;
  2620. ret.add(obj);
  2621. }
  2622. return ret;
  2623. } finally {
  2624. req.releaseConnection();
  2625. }
  2626. }
  2627. /**
  2628. * Returns the dependent objects
  2629. *
  2630. * @param uri the uri of the top-level object
  2631. * @return list of dependent objects
  2632. */
  2633. public List<JSONObject> usedBy(String uri) {
  2634. l.debug("Executing usedby uri=" + uri);
  2635. List<JSONObject> ret = new ArrayList<JSONObject>();
  2636. //HACK!
  2637. String usedUri = uri.replace("/obj/", "/usedby/");
  2638. HttpMethod req = createGetMethod(getServerUrl() + usedUri);
  2639. try {
  2640. String resp = executeMethodOk(req);
  2641. JSONObject parsedResp = JSONObject.fromObject(resp);
  2642. if (parsedResp == null || parsedResp.isNullObject() || parsedResp.isEmpty()) {
  2643. l.debug("Can't call usedby on uri=" + uri + ". Invalid response.");
  2644. throw new GdcRestApiException("Can't call usedby on uri=" + uri + ". Invalid response.");
  2645. }
  2646. JSONObject usedby = parsedResp.getJSONObject("usedby");
  2647. if (usedby == null || usedby.isNullObject() || usedby.isEmpty()) {
  2648. l.debug("Can't call usedby on uri=" + uri + ". No usedby data.");
  2649. throw new GdcRestApiException("Can't call usedby on uri=" + uri + ". No usedby data.");
  2650. }
  2651. JSONArray nodes = usedby.getJSONArray("nodes");
  2652. if (nodes == null) {
  2653. l.debug("Can't call usedby on uri=" + uri + ". No nodes key in the response.");
  2654. throw new GdcRestApiException("Can't call usedby on uri=" + uri + ". No nodes key in the response.");
  2655. }
  2656. for (Object o : nodes) {
  2657. JSONObject obj = (JSONObject) o;
  2658. ret.add(obj);
  2659. }
  2660. return ret;
  2661. } finally {
  2662. req.releaseConnection();
  2663. }
  2664. }
  2665. /**
  2666. * Creates a new object in the metadata server
  2667. *
  2668. * @param projectId project id (hash)
  2669. * @param content the new object content
  2670. * @return the new object
  2671. */
  2672. public JSONObject createMetadataObject(String projectId, JSON content) {
  2673. l.debug("Executing createMetadataObject on project id=" + projectId + "content='" + content.toString() + "'");
  2674. PostMethod req = createPostMethod(getProjectMdUrl(projectId) + OBJ_URI + "?createAndGet=true");
  2675. try {
  2676. String str = content.toString();
  2677. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(str.getBytes("utf-8")));
  2678. req.setRequestEntity(request);
  2679. String resp = executeMethodOk(req);
  2680. JSONObject parsedResp = JSONObject.fromObject(resp);
  2681. return parsedResp;
  2682. } catch (HttpMethodException ex) {
  2683. l.debug("Failed executing createMetadataObject on project id=" + projectId + "content='" + content.toString() + "'");
  2684. throw new GdcRestApiException("Failed executing createMetadataObject on project id=" + projectId + "content='" + content.toString() + "'", ex);
  2685. } catch (UnsupportedEncodingException e) {
  2686. l.debug("String#getBytes(\"utf-8\") threw UnsupportedEncodingException", e);
  2687. throw new IllegalStateException(e);
  2688. } finally {
  2689. req.releaseConnection();
  2690. }
  2691. }
  2692. /**
  2693. * Modifies an object in the metadata server
  2694. *
  2695. * @param projectId project id (hash)
  2696. * @param objectId object id (integer)
  2697. * @param content the new object content
  2698. * @return the new object
  2699. */
  2700. public JSONObject modifyMetadataObject(String projectId, int objectId, JSON content) {
  2701. l.debug("Executing modifyMetadataObject on project id=" + projectId + " objectId=" + objectId + " content='" + content.toString() + "'");
  2702. return modifyMetadataObject(MD_URI + projectId + OBJ_URI + "/" + objectId, content);
  2703. }
  2704. /**
  2705. * Modifies an object in the metadata server
  2706. *
  2707. * @param uri object uri
  2708. * @param content the new object content
  2709. * @return the new object
  2710. */
  2711. public JSONObject modifyMetadataObject(String uri, JSON content) {
  2712. l.debug("Executing modifyMetadataObject on uri=" + uri + " content='" + content.toString() + "'");
  2713. PostMethod req = createPostMethod(getServerUrl() + uri);
  2714. try {
  2715. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(
  2716. content.toString().getBytes("utf-8")));
  2717. req.setRequestEntity(request);
  2718. String resp = executeMethodOk(req);
  2719. JSONObject parsedResp = JSONObject.fromObject(resp);
  2720. return parsedResp;
  2721. } catch (HttpMethodException ex) {
  2722. l.debug("Failed executing modifyMetadataObject on uri=" + uri + " content='" + content.toString() + "'");
  2723. throw new GdcRestApiException("Failed executing modifyMetadataObject on uri=" + uri + " content='" + content.toString() + "'", ex);
  2724. } catch (UnsupportedEncodingException e) {
  2725. l.debug("String#getBytes(\"utf-8\") threw UnsupportedEncodingException", e);
  2726. throw new IllegalStateException(e);
  2727. } finally {
  2728. req.releaseConnection();
  2729. }
  2730. }
  2731. /**
  2732. * Deletes an object in the metadata server
  2733. *
  2734. * @param projectId project id (hash)
  2735. * @param objectId object id (integer)
  2736. * @return the new object
  2737. */
  2738. public void deleteMetadataObject(String projectId, int objectId) {
  2739. l.debug("Executing deleteMetadataObject on project id=" + projectId + " objectId=" + objectId);
  2740. deleteMetadataObject(MD_URI + projectId + OBJ_URI + "/" + objectId);
  2741. }
  2742. /**
  2743. * Deletes an object in the metadata server
  2744. *
  2745. * @param uri object uri
  2746. * @return the new object
  2747. */
  2748. public void deleteMetadataObject(String uri) {
  2749. l.debug("Executing deleteMetadataObject on project uri=" + uri);
  2750. DeleteMethod req = createDeleteMethod(getServerUrl() + uri);
  2751. try {
  2752. String resp = executeMethodOk(req);
  2753. } catch (HttpMethodException ex) {
  2754. l.debug("Failed executing deleteMetadataObject on project uri=" + uri);
  2755. throw new GdcRestApiException("Failed executing deleteMetadataObject on uri=" + uri, ex);
  2756. } finally {
  2757. req.releaseConnection();
  2758. }
  2759. }
  2760. /**
  2761. * Determines the projet's ETL mode (SLI/DLI/VOID)
  2762. *
  2763. * @param pid project id
  2764. * @return project's ETL mode
  2765. */
  2766. public String getProjectEtlMode(String pid) {
  2767. l.debug("Getting project etl status.");
  2768. GetMethod req = createGetMethod(getProjectMdUrl(pid) + ETL_MODE_URI);
  2769. try {
  2770. String resp = executeMethodOk(req);
  2771. JSONObject parsedResp = JSONObject.fromObject(resp);
  2772. if (parsedResp != null && !parsedResp.isNullObject() && !parsedResp.isEmpty()) {
  2773. JSONObject etlMode = parsedResp.getJSONObject("etlMode");
  2774. if (etlMode != null && !etlMode.isNullObject() && !etlMode.isEmpty()) {
  2775. String mode = etlMode.getString("mode");
  2776. if (mode != null && mode.length() > 0) {
  2777. return mode;
  2778. } else {
  2779. l.debug("Getting project etl status. No mode in the result: " + etlMode.toString());
  2780. throw new GdcRestApiException("Getting project etl status. No mode in the result: " + etlMode.toString());
  2781. }
  2782. } else {
  2783. l.debug("Getting project etl status. No etlMode in the result: " + parsedResp.toString());
  2784. throw new GdcRestApiException("Getting project etl status. No etlMode in the result: " + parsedResp.toString());
  2785. }
  2786. } else {
  2787. l.debug("Getting project etl status. Empty result.");
  2788. throw new GdcRestApiException("Getting project etl status. Empty result.");
  2789. }
  2790. } finally {
  2791. req.releaseConnection();
  2792. }
  2793. }
  2794. protected JSONObject getMigrationRequest(List<String> manifests) {
  2795. JSONObject etlMode = new JSONObject();
  2796. etlMode.put("mode", "SLI");
  2797. JSONArray mnfsts = new JSONArray();
  2798. mnfsts.addAll(manifests);
  2799. etlMode.put("sli", mnfsts);
  2800. JSONObject ret = new JSONObject();
  2801. ret.put("etlMode", etlMode);
  2802. return ret;
  2803. }
  2804. /**
  2805. * Checks if the migration is finished
  2806. *
  2807. * @param link the link returned from the start loading
  2808. * @return the loading status
  2809. */
  2810. public String getTaskManStatus(String link) throws HttpMethodException {
  2811. l.debug("Getting TaskMan status uri=" + link);
  2812. HttpMethod ptm = createGetMethod(getServerUrl() + link);
  2813. try {
  2814. String response = "";
  2815. boolean isFinished = false;
  2816. while (!isFinished) {
  2817. try {
  2818. response = executeMethodOk(ptm);
  2819. isFinished = true;
  2820. } catch (HttpMethodNotFinishedYetException e) {
  2821. l.debug("getTaskManStatus: Waiting for status");
  2822. try {
  2823. Thread.sleep(Constants.POLL_INTERVAL);
  2824. } catch (InterruptedException ex) {
  2825. // do nothing
  2826. }
  2827. }
  2828. }
  2829. JSONObject task = JSONObject.fromObject(response);
  2830. JSONObject state = task.getJSONObject("wTaskStatus");
  2831. if (state != null && !state.isNullObject() && !state.isEmpty()) {
  2832. String status = state.getString("status");
  2833. l.debug("TaskMan status=" + status);
  2834. return status;
  2835. } else {
  2836. l.debug("No wTaskStatus structure in the taskman status!");
  2837. throw new GdcRestApiException("No wTaskStatus structure in the taskman status!");
  2838. }
  2839. } finally {
  2840. ptm.releaseConnection();
  2841. }
  2842. }
  2843. public static class TaskmanStatus {
  2844. private String[] message;
  2845. private String status;
  2846. public TaskmanStatus(String s, String[] m) {
  2847. this.status = s;
  2848. this.message = m;
  2849. }
  2850. public String getStatus() {
  2851. return status;
  2852. }
  2853. public void setStatus(String status) {
  2854. this.status = status;
  2855. }
  2856. public String[] getMessage() {
  2857. return message;
  2858. }
  2859. public void setMessage(String[] message) {
  2860. this.message = message;
  2861. }
  2862. }
  2863. public TaskmanStatus getDetailedTaskManStatus(String link) throws HttpMethodException {
  2864. l.debug("Getting TaskMan status uri=" + link);
  2865. HttpMethod ptm = createGetMethod(getServerUrl() + link);
  2866. try {
  2867. String response = "";
  2868. boolean isFinished = false;
  2869. while (!isFinished) {
  2870. try {
  2871. response = executeMethodOk(ptm);
  2872. isFinished = true;
  2873. } catch (HttpMethodNotFinishedYetException e) {
  2874. l.debug("getTaskManStatus: Waiting for status");
  2875. try {
  2876. Thread.sleep(Constants.POLL_INTERVAL);
  2877. } catch (InterruptedException ex) {
  2878. // do nothing
  2879. }
  2880. }
  2881. }
  2882. JSONObject task = JSONObject.fromObject(response);
  2883. JSONObject state = task.getJSONObject("wTaskStatus");
  2884. if (state != null && !state.isNullObject() && !state.isEmpty()) {
  2885. String status = state.getString("status");
  2886. ArrayList<String> messages = new ArrayList<String>();
  2887. l.debug("TaskMan status=" + status);
  2888. if(state.containsKey("messages")) {
  2889. JSONArray msgs = state.getJSONArray("messages");
  2890. if(msgs != null && !msgs.isEmpty()) {
  2891. for (Object msgo : msgs) {
  2892. JSONObject msg = (JSONObject)msgo;
  2893. String root = (String)msg.keys().next();
  2894. JSONObject inner = msg.getJSONObject(root);
  2895. JSONArray prms = inner.getJSONArray("parameters");
  2896. String message = inner.getString("message");
  2897. if(prms != null && !prms.isEmpty()) {
  2898. for(Object prmo : prms) {
  2899. String prm = (String)prmo;
  2900. message = message.replaceFirst("\\%s",prm);
  2901. }
  2902. }
  2903. messages.add(message);
  2904. }
  2905. }
  2906. }
  2907. return new TaskmanStatus(status, (String[])messages.toArray(new String[]{}));
  2908. } else {
  2909. l.debug("No wTaskStatus structure in the taskman status!");
  2910. throw new GdcRestApiException("No wTaskStatus structure in the taskman status!");
  2911. }
  2912. } finally {
  2913. ptm.releaseConnection();
  2914. }
  2915. }
  2916. /**
  2917. * Migrates project datasets from DLI to SLI
  2918. *
  2919. * @param pid project ID
  2920. * @param manifests array of all dataset's manifests
  2921. */
  2922. public String migrateDataSets(String pid, List<String> manifests) {
  2923. l.debug("Migrating project to SLI.");
  2924. String currentMode = getProjectEtlMode(pid);
  2925. l.debug("Migrating project to SLI: current status is " + currentMode);
  2926. if (ETL_MODE_DLI.equalsIgnoreCase(currentMode) || ETL_MODE_VOID.equalsIgnoreCase(currentMode)) {
  2927. PostMethod req = createPostMethod(getProjectMdUrl(pid) + ETL_MODE_URI);
  2928. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(getMigrationRequest(manifests).toString().getBytes()));
  2929. req.setRequestEntity(request);
  2930. try {
  2931. String resp = executeMethodOk(req);
  2932. JSONObject responseObject = JSONObject.fromObject(resp);
  2933. String taskLink = responseObject.getString("uri");
  2934. return taskLink;
  2935. } catch (HttpMethodException ex) {
  2936. l.debug("Migrating project to SLI failed.", ex);
  2937. throw new GdcRestApiException("Migrating project to SLI failed.", ex);
  2938. } finally {
  2939. req.releaseConnection();
  2940. }
  2941. } else {
  2942. l.debug("Migrating project to SLI: no migration needed. Skipping.");
  2943. return "";
  2944. }
  2945. }
  2946. private static GetMethod createGetMethod(String path) {
  2947. return configureHttpMethod(new GetMethod(path));
  2948. }
  2949. private static PostMethod createPostMethod(String path) {
  2950. return configureHttpMethod(new PostMethod(path));
  2951. }
  2952. private static DeleteMethod createDeleteMethod(String path) {
  2953. return configureHttpMethod(new DeleteMethod(path));
  2954. }
  2955. private static PutMethod createPutMethod(String path) {
  2956. return configureHttpMethod(new PutMethod(path));
  2957. }
  2958. private static <T extends HttpMethod> T configureHttpMethod(T request) {
  2959. request.setRequestHeader("Content-Type", "application/json; charset=utf-8");
  2960. request.setRequestHeader("Accept", "application/json");
  2961. request.setRequestHeader("Accept-Charset", "utf-u");
  2962. request.setRequestHeader("User-Agent", "GoodData CL/1.2.67");
  2963. request.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
  2964. return request;
  2965. }
  2966. protected void finalize() throws Throwable {
  2967. try {
  2968. // logout();
  2969. } finally {
  2970. super.finalize();
  2971. }
  2972. }
  2973. /**
  2974. * API for querying users in a domain
  2975. *
  2976. * @param domain
  2977. * @return
  2978. */
  2979. public Map<String, GdcUser> getUsers(String domain) {
  2980. Map<String, GdcUser> users = new HashMap<String, GdcUser>();
  2981. String url = "/gdc/account/domains/" + domain + "/users";
  2982. JSONObject jsonObject = getObjectByUri(url);
  2983. if (jsonObject == null) {
  2984. return users;
  2985. }
  2986. JSONObject accountSettings = jsonObject
  2987. .getJSONObject("accountSettings");
  2988. if (accountSettings == null) {
  2989. return users;
  2990. }
  2991. JSONArray items = (JSONArray) accountSettings.get("items");
  2992. if (items == null) {
  2993. return users;
  2994. }
  2995. for (Object item : items) {
  2996. JSONObject itemJSON = JSONObject.fromObject(item);
  2997. if (itemJSON == null) {
  2998. continue;
  2999. }
  3000. JSONObject accountSetting = itemJSON
  3001. .getJSONObject("accountSetting");
  3002. if (accountSetting == null) {
  3003. continue;
  3004. }
  3005. GdcUser user = new GdcUser();
  3006. user.setLogin(accountSetting.getString("login"));
  3007. user.setFirstName(accountSetting.getString("firstName"));
  3008. user.setLastName(accountSetting.getString("lastName"));
  3009. user.setCompanyName(accountSetting.getString("companyName"));
  3010. user.setPosition(accountSetting.getString("position"));
  3011. user.setCountry(accountSetting.getString("country"));
  3012. user.setTimezone(accountSetting.getString("timezone"));
  3013. user.setPhoneNumber(accountSetting.getString("phoneNumber"));
  3014. user.setEmail(accountSetting.getString("email"));
  3015. JSONObject links = accountSetting.getJSONObject("links");
  3016. if (links == null)
  3017. throw new GdcException(
  3018. "The URL link for a user cannot be null: "
  3019. + user.getLogin());
  3020. String uri = links.getString("self");
  3021. if (uri == null)
  3022. throw new GdcException("The URL for a user cannot be null: "
  3023. + user.getLogin());
  3024. user.setUri(uri);
  3025. users.put(user.getLogin(), user);
  3026. }
  3027. return users;
  3028. }
  3029. public List<String> enumerateDimensions(String projectId) {
  3030. return enumerateResource(projectId, QUERY_DIMENSIONS);
  3031. }
  3032. public List<String> enumerateDataSets(String projectId) {
  3033. return enumerateResource(projectId, QUERY_DATASETS);
  3034. }
  3035. public List<String> enumerateFolders(String projectId) {
  3036. return enumerateResource(projectId, QUERY_FOLDERS);
  3037. }
  3038. public List<String> enumerateDashboards(String projectId) {
  3039. return enumerateResource(projectId, QUERY_PROJECTDASHBOARDS);
  3040. }
  3041. protected List<String> enumerateResource(String projectId, String resource) {
  3042. l.debug("Enumerating attributes for project id=" + projectId);
  3043. List<String> list = new ArrayList<String>();
  3044. String qUri = getProjectMdUrl(projectId) + QUERY_PREFIX + resource;
  3045. HttpMethod qGet = createGetMethod(qUri);
  3046. try {
  3047. String qr = executeMethodOk(qGet);
  3048. JSONObject q = JSONObject.fromObject(qr);
  3049. if (q.isNullObject()) {
  3050. l.debug("Enumerating "+resource+" for project id="+projectId+" failed.");
  3051. throw new GdcException(
  3052. "Enumerating "+resource+" for project id="+projectId+" failed.");
  3053. }
  3054. JSONObject qry = q.getJSONObject("query");
  3055. if (qry.isNullObject()) {
  3056. l.debug("Enumerating "+resource+" for project id="+projectId+" failed.");
  3057. throw new GdcException(
  3058. "Enumerating "+resource+" for project id="+projectId+" failed.");
  3059. }
  3060. JSONArray entries = qry.getJSONArray("entries");
  3061. if (entries == null) {
  3062. l.debug("Enumerating "+resource+" for project id="+projectId+" failed.");
  3063. throw new GdcException(
  3064. "Enumerating "+resource+" for project id="+projectId+" failed.");
  3065. }
  3066. for (Object oentry : entries) {
  3067. JSONObject entry = (JSONObject) oentry;
  3068. list.add(entry.getString("link"));
  3069. }
  3070. } finally {
  3071. qGet.releaseConnection();
  3072. }
  3073. return list;
  3074. }
  3075. public ProjectExportResult exportMDByUrl(String projectId, List<String> urls) {
  3076. l.debug("Exporting metadata objects with URls " + urls
  3077. + " from project " + projectId);
  3078. PostMethod req = createPostMethod(getProjectMdUrl(projectId)
  3079. + PROJECT_PARTIAL_EXPORT_URI);
  3080. JSONObject param = getMDExportStructureStrings(projectId, urls);
  3081. InputStreamRequestEntity request = new InputStreamRequestEntity(
  3082. new ByteArrayInputStream(param.toString().getBytes(
  3083. Charset.forName("UTF-8"))));
  3084. req.setRequestEntity(request);
  3085. ProjectExportResult result = null;
  3086. try {
  3087. String response = executeMethodOk(req);
  3088. result = new ProjectExportResult();
  3089. JSONObject responseObject = JSONObject.fromObject(response);
  3090. JSONObject exportArtifact = responseObject
  3091. .getJSONObject("partialMDArtifact");
  3092. JSONObject status = exportArtifact.getJSONObject("status");
  3093. result.setTaskUri(status.getString("uri"));
  3094. result.setExportToken(exportArtifact.getString("token"));
  3095. return result;
  3096. } catch (HttpMethodException ex) {
  3097. l.debug("Error exporting metadata objects with URls " + urls
  3098. + " from project " + projectId, ex);
  3099. throw new GdcRestApiException(
  3100. "Error exporting metadata objects with URls " + urls
  3101. + " from project " + projectId, ex);
  3102. } finally {
  3103. req.releaseConnection();
  3104. }
  3105. }
  3106. protected JSONObject getMDExportStructureStrings(String projectId,
  3107. List<String> urls) {
  3108. JSONObject param = new JSONObject();
  3109. JSONObject partialMDExport = new JSONObject();
  3110. JSONArray uris = new JSONArray();
  3111. for (String url : urls) {
  3112. uris.add(url);
  3113. }
  3114. partialMDExport.put("uris", uris);
  3115. param.put("partialMDExport", partialMDExport);
  3116. return param;
  3117. }
  3118. public NamePasswordConfiguration getNamePasswordConfiguration() {
  3119. return config;
  3120. }
  3121. /**
  3122. * Checks if report copying is finished. Workaround implementation due to
  3123. * wrong handling of status code.
  3124. *
  3125. * @param link
  3126. * the link returned from the start loading
  3127. * @return the loading status
  3128. */
  3129. public String getCopyStatus(String link) {
  3130. l.debug("Getting Cloning Status status uri=" + link);
  3131. HttpMethod ptm = createGetMethod(getServerUrl() + link);
  3132. try {
  3133. String response = executeMethodOk(ptm);
  3134. if (response != null && !response.isEmpty()) {
  3135. JSONObject task = JSONObject.fromObject(response);
  3136. JSONObject state = task.getJSONObject("taskState");
  3137. if (state != null && !state.isNullObject() && !state.isEmpty()) {
  3138. String status = state.getString("status");
  3139. l.debug("TaskMan status=" + status);
  3140. return status;
  3141. } else {
  3142. l.debug("No wTaskStatus structure in the migration status!");
  3143. throw new GdcRestApiException(
  3144. "No wTaskStatus structure in the migration status!");
  3145. }
  3146. }
  3147. return "RUNNING";
  3148. } catch (HttpMethodException e) {
  3149. // workaround implementation due to wrong handling (at least for
  3150. // this status)
  3151. if (e instanceof HttpMethodNotFinishedYetException
  3152. || (e.getCause() != null && e.getCause() instanceof HttpMethodNotFinishedYetException)) {
  3153. l.debug("getTaskManStatus: Waiting for status");
  3154. return "RUNNING";
  3155. }
  3156. throw e;
  3157. } finally {
  3158. ptm.releaseConnection();
  3159. }
  3160. }
  3161. /**
  3162. * Retrieves the project info by the project's name
  3163. *
  3164. * @param name
  3165. * the project name
  3166. * @return the GoodDataProjectInfo populated with the project's information
  3167. * @throws HttpMethodException
  3168. * @throws GdcProjectAccessException
  3169. */
  3170. @Deprecated
  3171. public Project getProjectByName(String name) throws HttpMethodException,
  3172. GdcProjectAccessException {
  3173. l.debug("Getting project by name=" + name);
  3174. for (Iterator<JSONObject> linksIter = getProjectsLinks(); linksIter
  3175. .hasNext();) {
  3176. JSONObject link = linksIter.next();
  3177. String cat = link.getString("category");
  3178. if (!"project".equalsIgnoreCase(cat)) {
  3179. continue;
  3180. }
  3181. String title = link.getString("title");
  3182. if (title.equals(name)) {
  3183. Project proj = new Project(link);
  3184. l.debug("Got project by name=" + name);
  3185. return proj;
  3186. }
  3187. }
  3188. l.debug("The project name=" + name + " doesn't exists.");
  3189. throw new GdcProjectAccessException("The project name=" + name
  3190. + " doesn't exists.");
  3191. }
  3192. /**
  3193. * Returns the existing projects links
  3194. *
  3195. * @return accessible projects links
  3196. * @throws com.gooddata.exception.HttpMethodException
  3197. */
  3198. @Deprecated
  3199. @SuppressWarnings("unchecked")
  3200. private Iterator<JSONObject> getProjectsLinks() throws HttpMethodException {
  3201. l.debug("Getting project links.");
  3202. HttpMethod req = createGetMethod(getServerUrl() + MD_URI);
  3203. try {
  3204. String resp = executeMethodOk(req);
  3205. JSONObject parsedResp = JSONObject.fromObject(resp);
  3206. JSONObject about = parsedResp.getJSONObject("about");
  3207. JSONArray links = about.getJSONArray("links");
  3208. l.debug("Got project links " + links);
  3209. return links.iterator();
  3210. } finally {
  3211. req.releaseConnection();
  3212. }
  3213. }
  3214. /**
  3215. * Create a new GoodData project
  3216. *
  3217. * @param name
  3218. * project name
  3219. * @param desc
  3220. * project description
  3221. * @param templateUri
  3222. * project template uri
  3223. * @return the project Id
  3224. * @throws GdcRestApiException
  3225. */
  3226. @Deprecated
  3227. public String createProject(String name, String desc, String templateUri)
  3228. throws GdcRestApiException {
  3229. return this.createProject(name, desc, templateUri, null, null);
  3230. }
  3231. /**
  3232. * Returns the List of GoodDataProjectInfo structures for the accessible
  3233. * projects
  3234. *
  3235. * @return the List of GoodDataProjectInfo structures for the accessible
  3236. * projects
  3237. * @throws HttpMethodException
  3238. */
  3239. @Deprecated
  3240. public List<Project> listProjects() throws HttpMethodException {
  3241. l.debug("Listing projects.");
  3242. List<Project> list = new ArrayList<Project>();
  3243. for (Iterator<JSONObject> linksIter = getProjectsLinks(); linksIter
  3244. .hasNext();) {
  3245. JSONObject link = linksIter.next();
  3246. String cat = link.getString("category");
  3247. if (!"project".equalsIgnoreCase(cat)) {
  3248. continue;
  3249. }
  3250. Project proj = new Project(link);
  3251. list.add(proj);
  3252. }
  3253. l.debug("Found projects " + list);
  3254. return list;
  3255. }
  3256. /**
  3257. * Gets a report definition from the report uri (/gdc/obj...)
  3258. *
  3259. * @param reportUri report uri (/gdc/obj...)
  3260. * @return report definition
  3261. */
  3262. @Deprecated
  3263. public String getReportDefinition(String reportUri) {
  3264. l.debug( "Getting report definition for report uri=" + reportUri );
  3265. String qUri = getServerUrl() + reportUri;
  3266. HttpMethod qGet = createGetMethod( qUri );
  3267. try {
  3268. String qr = executeMethodOk( qGet );
  3269. JSONObject q = JSONObject.fromObject( qr );
  3270. if (q.isNullObject()) {
  3271. l.debug("Error getting report definition for report uri=" + reportUri);
  3272. throw new GdcProjectAccessException("Error getting report definition for report uri=" + reportUri);
  3273. }
  3274. JSONObject report = q.getJSONObject("report");
  3275. if (report.isNullObject()) {
  3276. l.debug("Error getting report definition for report uri=" + reportUri);
  3277. throw new GdcProjectAccessException("Error getting report definition for report uri=" + reportUri);
  3278. }
  3279. JSONObject content = report.getJSONObject("content");
  3280. if (content.isNullObject()) {
  3281. l.debug("Error getting report definition for report uri=" + reportUri);
  3282. throw new GdcProjectAccessException("Error getting report definition for report uri=" + reportUri);
  3283. }
  3284. JSONArray definitions = content.getJSONArray("definitions");
  3285. if (definitions == null) {
  3286. l.debug("Error getting report definition for report uri=" + reportUri);
  3287. throw new GdcProjectAccessException("Error getting report definition for report uri=" + reportUri);
  3288. }
  3289. if (definitions.size() > 0) {
  3290. String lastDefUri = definitions.getString(definitions.size() - 1);
  3291. qUri = getServerUrl() + lastDefUri;
  3292. return lastDefUri;
  3293. }
  3294. else {
  3295. l.debug("Error getting report definition for report uri=" + reportUri);
  3296. throw new GdcProjectAccessException("Error getting report definition for report uri=" + reportUri);
  3297. }
  3298. } finally {
  3299. if (qGet != null)
  3300. qGet.releaseConnection();
  3301. }
  3302. }
  3303. /**
  3304. * Returns the create project JSON structure
  3305. *
  3306. * @param name
  3307. * project name
  3308. * @param desc
  3309. * project description
  3310. * @param templateUri
  3311. * project template uri
  3312. * @return the create project JSON structure
  3313. */
  3314. @Deprecated
  3315. private JSONObject getCreateProject(String name, String desc,
  3316. String templateUri) {
  3317. JSONObject meta = new JSONObject();
  3318. meta.put("title", name);
  3319. meta.put("summary", desc);
  3320. if (templateUri != null && templateUri.length() > 0) {
  3321. meta.put("projectTemplate", templateUri);
  3322. }
  3323. JSONObject content = new JSONObject();
  3324. // content.put("state", "ENABLED");
  3325. content.put("guidedNavigation", "1");
  3326. JSONObject project = new JSONObject();
  3327. project.put("meta", meta);
  3328. project.put("content", content);
  3329. JSONObject createStructure = new JSONObject();
  3330. createStructure.put("project", project);
  3331. return createStructure;
  3332. }
  3333. public void putUser(String uri, GdcUser user)
  3334. throws GdcRestApiException {
  3335. if (user != null) {
  3336. l.debug("Updating existing user id " + uri);
  3337. PutMethod req = createPutMethod(getServerUrl() + uri );
  3338. JSONObject param = getCreateUserStructure(user);
  3339. InputStreamRequestEntity request = new InputStreamRequestEntity(new ByteArrayInputStream(
  3340. param.toString().getBytes()));
  3341. req.setRequestEntity(request);
  3342. try {
  3343. executeMethodOk(req);
  3344. } catch (HttpMethodException ex) {
  3345. l.debug("Error updating user ", ex);
  3346. throw new GdcRestApiException("Error updating user ", ex);
  3347. } finally {
  3348. req.releaseConnection();
  3349. }
  3350. } else {
  3351. throw new InvalidParameterException("The user must not be null.");
  3352. }
  3353. }
  3354. }