1 package com.pentila.entSavoie.edx;
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.InputStreamReader;
6 import java.io.UnsupportedEncodingException;
8 import java.net.URLEncoder;
9 import java.text.Normalizer;
10 import java.text.SimpleDateFormat;
11 import java.util.ArrayList;
12 import java.util.Date;
13 import java.util.List;
15 import javax.net.ssl.HttpsURLConnection;
17 import org.apache.commons.lang.RandomStringUtils;
18 import org.apache.http.HttpResponse;
19 import org.apache.http.NameValuePair;
20 import org.apache.http.client.HttpClient;
21 import org.apache.http.client.entity.UrlEncodedFormEntity;
22 import org.apache.http.client.methods.HttpPost;
23 import org.apache.http.entity.ByteArrayEntity;
24 import org.apache.http.impl.client.DefaultHttpClient;
25 import org.apache.http.message.BasicNameValuePair;
26 import org.jsoup.Jsoup;
27 import org.jsoup.nodes.Document;
28 import org.jsoup.nodes.Element;
29 import org.jsoup.select.Elements;
31 import com.liferay.portal.kernel.exception.PortalException;
32 import com.liferay.portal.kernel.exception.SystemException;
33 import com.liferay.portal.kernel.json.JSONArray;
34 import com.liferay.portal.kernel.json.JSONException;
35 import com.liferay.portal.kernel.json.JSONFactoryUtil;
36 import com.liferay.portal.kernel.json.JSONObject;
37 import com.liferay.portal.kernel.log.Log;
38 import com.liferay.portal.kernel.log.LogFactoryUtil;
39 import com.liferay.portal.model.Role;
40 import com.liferay.portal.model.User;
41 import com.liferay.portal.service.RoleLocalServiceUtil;
42 import com.pentila.entSavoie.ENTRolesConstants;
43 import com.pentila.entSavoie.edx.model.EdxCourse;
44 import com.pentila.entSavoie.edx.model.EdxUser;
45 import com.pentila.entSavoie.edx.service.EdxCourseLocalServiceUtil;
46 import com.pentila.entSavoie.edx.service.EdxUserLocalServiceUtil;
47 import com.pentila.entSavoie.utils.ENTMainUtilsLocalServiceUtil;
49 public class EdxWebServiceUtil {
51 private static final String USER_AGENT = "Mozilla/5.0";
52 private static final String EDX_BASE_URL = ENTMainUtilsLocalServiceUtil.getEdxBaseUrl();
53 private static final String EDX_USER_CREATION_URL = "/user_api/v1/account/registration/";
54 private static final String EDX_USER_ENROLLMENT_URL = "/api/enrollment/v1/enrollment";
55 private static final String EDX_COURSES_URL = "/api/courses/v1/courses";
56 private static final String EDX_BLOCKS_URL = "/api/courses/v1/blocks/";
58 private static final String ACCESS_TOKEN = "Bearer " + ENTMainUtilsLocalServiceUtil.getEdxAccessToken();
59 private static final int MAX_USERNAME_LENGTH = 30;
60 private static final int HTTP_CODE_OK = 200;
62 private static Log _log = LogFactoryUtil.getLog(EdxWebServiceUtil.class);
65 * Update the list of teacher courses
69 * @throws PortalException
70 * @throws SystemException
72 public static void updateTeacherCourses(User teacher) throws IOException, PortalException, SystemException {
74 JSONArray coursesList = JSONFactoryUtil.createJSONArray();
75 final String dateFormat = "yyyy-MM-dd'T'hh:mm:ss'Z'";
77 // Get teacher's edx username
78 EdxUser edxUser = EdxUserLocalServiceUtil.getEdxUser(teacher.getUserId());
79 if (edxUser == null) {
80 _log.error("Teacher " + teacher.getFullName() + " does not exist in database");
84 String url = EDX_BASE_URL + EDX_COURSES_URL + "/?org=" + edxUser.getEdxUsername();
88 String response = sendGet(url);
89 if (response.equals("")) {
90 _log.error("Error : http get request to update teacher courses returns response " + response);
93 JSONObject jsonResponse = parseDjangoApiResponse(response);
95 JSONArray coursesListTmp = jsonResponse.getJSONArray("results");
96 for (int i = 0; i < coursesListTmp.length(); i++) {
97 coursesList.put(coursesListTmp.getJSONObject(i));
99 if (jsonResponse.has("pagination") && jsonResponse.getJSONObject("pagination").has("next")
100 && !jsonResponse.getJSONObject("pagination").getString("next").isEmpty()) {
101 url = jsonResponse.getJSONObject("pagination").getString("next");
105 } while (!url.trim().isEmpty());
107 _log.info("Parsed " + coursesList.length() + " courses");
109 for (int i = 0; i < coursesList.length(); i++) {
110 JSONObject jsonCourse = coursesList.getJSONObject(i);
111 String courseId = jsonCourse.getString(EdxConstants.EDX_API_TEACHER_COURSE_COURSE_ID);
112 _log.info("Found course_id " + courseId);
114 // Keep only courses with teacher's name in it
115 // This is due to hack done in edx that hardcodes the course's
116 // organization name as the teacher username
117 if (courseId.contains(edxUser.getEdxUsername())) {
119 // Parse course informations
120 EdxCourse edxCourse = EdxCourseLocalServiceUtil.addTeacherCourse(teacher.getUserId(),
121 jsonCourse.getString(EdxConstants.EDX_API_TEACHER_COURSE_COURSE_ID));
122 edxCourse.setCourseName(jsonCourse.getString("name"));
123 if (!jsonCourse.getString(EdxConstants.EDX_API_TEACHER_COURSE_START).equals("")) {
124 Date courseStartDate = new SimpleDateFormat(dateFormat)
125 .parse(jsonCourse.getString(EdxConstants.EDX_API_TEACHER_COURSE_START));
126 edxCourse.setCourseStartDate(courseStartDate);
128 if (!jsonCourse.getString(EdxConstants.EDX_API_TEACHER_COURSE_ENROLLMENT_START).equals("")) {
129 Date enrollMentStartDate = new SimpleDateFormat(dateFormat)
130 .parse(jsonCourse.getString(EdxConstants.EDX_API_TEACHER_COURSE_ENROLLMENT_START));
131 edxCourse.setEnrollmentStartDate(enrollMentStartDate);
133 if (!jsonCourse.getString(EdxConstants.EDX_API_TEACHER_COURSE_ENROLLMENT_END).equals("")) {
134 Date enrollmentEndDate = new SimpleDateFormat(dateFormat)
135 .parse(jsonCourse.getString(EdxConstants.EDX_API_TEACHER_COURSE_ENROLLMENT_END));
136 edxCourse.setEnrollmentEndDate(enrollmentEndDate);
138 edxCourse.setDescription(jsonCourse.getString(EdxConstants.EDX_API_TEACHER_COURSE_SHORT_DESC));
139 edxCourse.setNumber(jsonCourse.getString(EdxConstants.EDX_API_TEACHER_COURSE_NUMBER));
140 EdxCourseLocalServiceUtil.updateEdxCourse(edxCourse);
142 synchronizeCourse(jsonCourse.getString(EdxConstants.EDX_API_TEACHER_COURSE_COURSE_ID));
143 _log.info("Synchronized course structure");
149 } catch (Exception e) {
150 _log.error("Error when getting the list of courses", e);
156 * Enroll a student in a course
162 public static boolean enrollStudentInCourse(User student, String courseId) {
164 // Create edx user if it does not already exist
165 EdxUser edxUser = null;
167 edxUser = EdxUserLocalServiceUtil.getEdxUser(student.getUserId());
168 } catch (Exception e) {
169 _log.error("Error when getting edx user for userId " + student.getFullName());
171 if (edxUser == null) {
173 edxUser = createUserInEdx(student);
174 } catch (Exception e) {
175 _log.error("Error when creating edx user for userId " + student.getFullName());
179 // Now enroll the student into the course
180 String wsUrl = EDX_BASE_URL + EDX_USER_ENROLLMENT_URL;
182 JSONObject courseDetails = JSONFactoryUtil.createJSONObject();
183 courseDetails.put(EdxConstants.EDX_API_ENROLL_COURSE_ID, courseId);
184 JSONObject json = JSONFactoryUtil.createJSONObject();
185 json.put(EdxConstants.EDX_API_ENROLL_USER, edxUser.getEdxUsername());
186 json.put(EdxConstants.EDX_API_ENROLL_COURSE_DETAILS, courseDetails);
188 String postResponse = sendJsonPost(wsUrl, json.toString());
190 // Parse returned json to check student's enrollment
191 return checkUserEnrollment(postResponse, courseId);
192 } catch (Exception e) {
193 _log.error("Error when enrolling student " + student.getFullName() + " in course " + courseId, e);
199 * Create a user in the edx mapping table
202 * @return the created user
205 public static EdxUser createUserInEdx(User user) throws Exception {
207 Role nat1Role = RoleLocalServiceUtil.getRole(user.getCompanyId(), ENTRolesConstants.NATIONAL_1);
208 Role nat2Role = RoleLocalServiceUtil.getRole(user.getCompanyId(), ENTRolesConstants.NATIONAL_2);
209 Role nat3Role = RoleLocalServiceUtil.getRole(user.getCompanyId(), ENTRolesConstants.NATIONAL_3);
210 Role nat4Role = RoleLocalServiceUtil.getRole(user.getCompanyId(), ENTRolesConstants.NATIONAL_4);
213 String wsUrl = EDX_BASE_URL + EDX_USER_CREATION_URL;
215 List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
216 urlParameters.add(new BasicNameValuePair(EdxConstants.EDX_API_CREATE_USER_EMAIL, user.getEmailAddress()));
218 String username = buildUserName(user);
219 urlParameters.add(new BasicNameValuePair(EdxConstants.EDX_API_CREATE_USER_USERNAME, username));
220 urlParameters.add(new BasicNameValuePair(EdxConstants.EDX_API_CREATE_USER_NAME,
221 user.getLastName() + " " + user.getFirstName()));
222 urlParameters.add(new BasicNameValuePair(EdxConstants.EDX_API_CREATE_USER_FIRSTNAME, user.getFirstName()));
223 urlParameters.add(new BasicNameValuePair(EdxConstants.EDX_API_CREATE_USER_LASTNAME, user.getLastName()));
226 if (RoleLocalServiceUtil.hasUserRole(user.getUserId(), nat1Role.getRoleId()) && RoleLocalServiceUtil.hasUserRole(user.getUserId(), nat2Role.getRoleId())){
227 urlParameters.add(new BasicNameValuePair(EdxConstants.EDX_API_CREATE_USER_ROLE, "4"));
228 urlParameters.add(new BasicNameValuePair(EdxConstants.EDX_API_CREATE_USER_IS_STAFF, "0"));
230 else if(RoleLocalServiceUtil.hasUserRole(user.getUserId(), nat4Role.getRoleId())){
231 urlParameters.add(new BasicNameValuePair(EdxConstants.EDX_API_CREATE_USER_ROLE, "1"));
232 urlParameters.add(new BasicNameValuePair(EdxConstants.EDX_API_CREATE_USER_IS_STAFF, "1"));
234 else if(RoleLocalServiceUtil.hasUserRole(user.getUserId(), nat3Role.getRoleId())){
235 urlParameters.add(new BasicNameValuePair(EdxConstants.EDX_API_CREATE_USER_ROLE, "3"));
236 urlParameters.add(new BasicNameValuePair(EdxConstants.EDX_API_CREATE_USER_IS_STAFF, "0"));
240 // Password is a random string : 4 first letters are 'Nat3' in case of a
242 // This is a hack in edx that allows to set 'is_staff' to the right
243 // value without having to update user's account through a new api call
244 String shortRole = "rand";
245 if (RoleLocalServiceUtil.hasUserRole(user.getUserId(), nat3Role.getRoleId())) {
248 String password = shortRole + RandomStringUtils.randomAlphanumeric(16);
249 urlParameters.add(new BasicNameValuePair(EdxConstants.EDX_API_CREATE_USER_PASSWORD, password));
250 urlParameters.add(new BasicNameValuePair(EdxConstants.EDX_API_CREATE_USER_HONOR_CODE, "true"));
251 urlParameters.add(new BasicNameValuePair(EdxConstants.EDX_API_CREATE_USER_TERMS, "true"));
252 _log.info("About to create user in edx with username " + username + " and password " + password);
254 boolean isCreatedInEdx = false;
256 String postResponse = "";
257 int responseCode = sendValuePairPost(wsUrl, urlParameters, postResponse);
258 if (responseCode == 200) {
259 _log.info("User creation in edx went fine for " + user.getFullName());
260 isCreatedInEdx = true;
261 } else if (responseCode == 409) {
262 _log.info("User " + user.getFullName() + " already exists in edx ");
263 isCreatedInEdx = true;
265 _log.info("User creation in edx is in error for " + user.getFullName() + " : post response is "
268 } catch (Exception e) {
269 _log.error("Error when creating edx account for user " + user.getFullName(), e);
272 if (isCreatedInEdx) {
273 EdxUser edxUser = null;
275 edxUser = EdxUserLocalServiceUtil.getEdxUser(user.getUserId());
276 } catch (Exception e) {
278 if (edxUser == null) {
279 edxUser = EdxUserLocalServiceUtil.createEdxUser(user.getUserId());
280 edxUser.setEdxPassword(password);
281 edxUser.setEdxUsername(username);
282 EdxUserLocalServiceUtil.updateEdxUser(edxUser);
290 * Parses the html response and extract the useful data into a JSON object
295 private static JSONObject parseDjangoApiResponse(String response) {
297 JSONObject jsonResp = null;
299 jsonResp = JSONFactoryUtil.createJSONObject(response);
300 } catch (JSONException e) {
303 if (jsonResp == null) {
305 Document doc = Jsoup.parse(response);
306 Elements elements = doc.getElementsByAttributeValue("class", "response-info");
307 Element element = elements.get(0);
308 Element preElement = element.getElementsByTag("pre").get(0);
309 String text = preElement.text();
310 String resp = text.substring(text.indexOf("{"));
311 jsonResp = JSONFactoryUtil.createJSONObject(resp);
312 } catch (Exception e) {
313 _log.error("Error when parsing HTML response into Json structure. Html is " + response, e);
320 * Parses the json response and extract the useful data into a JSON object
321 * Input Json string contains, for a given user, the list of courses he is
327 private static boolean checkUserEnrollment(String postResponse, String courseId) {
330 if (postResponse.contains("does not exist")) {
331 _log.error("User does not exist !");
335 JSONObject jsonResp = JSONFactoryUtil.createJSONObject(postResponse);
336 JSONObject courseDetails = jsonResp.getJSONObject(EdxConstants.EDX_API_ENROLL_COURSE_DETAILS);
337 String returnedCourseId = courseDetails.getString(EdxConstants.EDX_API_ENROLL_COURSE_ID);
338 if (returnedCourseId.equals(courseId)) {
341 } catch (Exception e) {
342 _log.error("Error when parsing the usercourses json response : " + postResponse, e);
344 _log.error("User was not enrolled correctly in courseId " + courseId);
348 public static void synchronizeCourse(String courseId) {
350 String encodedCourseId = "";
352 encodedCourseId = URLEncoder.encode(courseId, "UTF-8");
353 } catch (UnsupportedEncodingException e) {
354 _log.error("Error when url-encoding courseId " + courseId, e);
356 if (!encodedCourseId.equals("")) {
358 String wsUrl = EDX_BASE_URL + EDX_BLOCKS_URL + "?course_id=" + encodedCourseId // The
361 + "&all_blocks=true" // Replace this parameter by 'username'
362 // parameter if we want to get all
363 // blocks for a given student
364 + "&depth=all" // Return the whole course structure
365 + "&requested_fields=children"; // The 'children' key
366 // describes the children
369 String getResponse = sendGet(wsUrl);
370 if (getResponse.equals("")) {
371 _log.error("Http get request to get course details failed with response " + getResponse);
374 JSONObject jsonCourseBlocks = parseDjangoApiResponse(getResponse);
375 _log.info("contenu jsonCourseBlocks " + jsonCourseBlocks);
377 JSONObject structuredCourse = parseCourseBlocks(jsonCourseBlocks);
379 // add the more information of course
380 boolean isCourseBlockInfoModified = false;
381 EdxCourse edxCourse = EdxCourseLocalServiceUtil.getEdxCourse(courseId);
382 if (!edxCourse.getDisplayName()
383 .equals(structuredCourse.getString(EdxConstants.EDX_API_BLOCKS_DISPLAY_NAME))) {
384 edxCourse.setDisplayName(structuredCourse.getString(EdxConstants.EDX_API_BLOCKS_DISPLAY_NAME));
385 isCourseBlockInfoModified = true;
387 if (!edxCourse.getLmsWebUrl()
388 .equals(structuredCourse.getString(EdxConstants.EDX_API_BLOCKS_LMS_WEB_URL))) {
389 edxCourse.setLmsWebUrl(structuredCourse.getString(EdxConstants.EDX_API_BLOCKS_LMS_WEB_URL));
390 isCourseBlockInfoModified = true;
392 if (!edxCourse.getStudentViewUrl()
393 .equals(structuredCourse.getString(EdxConstants.EDX_API_BLOCKS_STUDENT_VIEW_URL))) {
394 edxCourse.setStudentViewUrl(
395 structuredCourse.getString(EdxConstants.EDX_API_BLOCKS_STUDENT_VIEW_URL));
396 isCourseBlockInfoModified = true;
398 if (isCourseBlockInfoModified) {
399 EdxCourseLocalServiceUtil.updateEdxCourse(edxCourse, false);
402 EdxSynchronizationUtils.synchronizeCourseSections(courseId, structuredCourse.getJSONArray("sections"));
403 } catch (Exception e) {
404 _log.error("Error when getting course blocks for courseId " + courseId, e);
410 * Parses the course blocks structure and fill the DB
412 * @param jsonCourseBlocks
414 private static JSONObject parseCourseBlocks(JSONObject jsonCourseBlocks) {
416 JSONObject structuredCourse = JSONFactoryUtil.createJSONObject();
418 String courseId = jsonCourseBlocks.getString(EdxConstants.EDX_API_BLOCKS_ROOT);
419 JSONObject allBlocks = jsonCourseBlocks.getJSONObject(EdxConstants.EDX_API_BLOCKS_BLOCKS);
420 structuredCourse.put("courseId", courseId);
422 // Get sections (chapters)
423 JSONArray courseIdArray = JSONFactoryUtil.createJSONArray();
424 courseIdArray.put(courseId);
425 JSONArray courses = getChildrenBlocks(allBlocks, courseIdArray, EdxConstants.EDX_API_BLOCKS_TYPE_COURSE);
426 if (courses == null || courses.length() != 1) {
427 _log.error("Error : there is more than 1 course in the course block list");
428 return structuredCourse;
430 JSONObject course = courses.getJSONObject(0);
431 structuredCourse.put(EdxConstants.EDX_API_BLOCKS_DISPLAY_NAME,
432 course.getString(EdxConstants.EDX_API_BLOCKS_DISPLAY_NAME));
433 structuredCourse.put(EdxConstants.EDX_API_BLOCKS_STUDENT_VIEW_URL,
434 course.getString(EdxConstants.EDX_API_BLOCKS_STUDENT_VIEW_URL));
435 structuredCourse.put(EdxConstants.EDX_API_BLOCKS_LMS_WEB_URL,
436 course.getString(EdxConstants.EDX_API_BLOCKS_LMS_WEB_URL));
437 structuredCourse.put("id", course.getString(EdxConstants.EDX_API_BLOCKS_ID));
438 JSONArray sections = getChildrenBlocks(allBlocks, course.getJSONArray(EdxConstants.EDX_API_BLOCKS_CHILDREN),
439 EdxConstants.EDX_API_BLOCKS_TYPE_CHAPTER);
441 // Loop over sections to get sub-sections
442 for (int i = 0; i < sections.length(); i++) {
443 JSONObject section = sections.getJSONObject(i);
444 JSONArray subSections = getChildrenBlocks(allBlocks,
445 section.getJSONArray(EdxConstants.EDX_API_BLOCKS_CHILDREN),
446 EdxConstants.EDX_API_BLOCKS_TYPE_SEQUENTIAL);
447 section.put("subSections", subSections);
449 // Loop over subSections to get units
450 for (int j = 0; j < subSections.length(); j++) {
451 JSONObject subSection = subSections.getJSONObject(j);
452 JSONArray units = getChildrenBlocks(allBlocks,
453 subSection.getJSONArray(EdxConstants.EDX_API_BLOCKS_CHILDREN),
454 EdxConstants.EDX_API_BLOCKS_TYPE_VERTICAL);
455 subSection.put("units", units);
457 // Loop over units to get items
458 for (int k = 0; k < units.length(); k++) {
459 JSONObject unit = units.getJSONObject(k);
460 JSONArray items = getChildrenBlocks(allBlocks,
461 unit.getJSONArray(EdxConstants.EDX_API_BLOCKS_CHILDREN),
462 EdxConstants.EDX_API_BLOCKS_TYPE_ALL);
463 unit.put("items", items);
467 structuredCourse.put("sections", sections);
468 _log.info("le contenu de structuredCourse : " + structuredCourse.toString());
469 return structuredCourse;
473 * Returns an array of JSONObjects, given their ids, among the 'allBlocks'
474 * list, with given type
477 * @param childrenBlockIds
481 private static JSONArray getChildrenBlocks(JSONObject allBlocks, JSONArray childrenBlockIds, String type) {
483 JSONArray result = JSONFactoryUtil.createJSONArray();
484 if (childrenBlockIds != null) {
485 // Compare blockId and type
486 for (int j = 0; j < childrenBlockIds.length(); j++) {
488 String childBlockId = childrenBlockIds.getString(j);
489 JSONObject block = allBlocks.getJSONObject(childBlockId);
490 if (block.getString(EdxConstants.EDX_API_BLOCKS_TYPE).equals(type)
491 || type.equals(EdxConstants.EDX_API_BLOCKS_TYPE_ALL)) {
494 _log.error("Error when parsing blockId" + childBlockId + ". It has wrong type ("
495 + block.getString(EdxConstants.EDX_API_BLOCKS_TYPE) + " instead of " + type + ")");
499 _log.info("le contenu de getChildrenBlocks : " + result.toString());
504 * Send HTTP POST request
507 * @param urlParameters
508 * - the map of parameters
512 private static String sendJsonPost(String url, String params) throws Exception {
514 HttpClient client = new DefaultHttpClient();
515 HttpPost post = new HttpPost(url);
517 post.setHeader("User-Agent", USER_AGENT);
518 post.setHeader("Content-type", "application/json");
519 post.setHeader("Authorization", ACCESS_TOKEN);
521 post.setEntity(new ByteArrayEntity(params.getBytes("UTF8")));
522 HttpResponse response = client.execute(post);
524 _log.info("Sending POST request to URL : " + url);
525 _log.info("Post parameters : " + params);
526 _log.info("Response Code : " + response.getStatusLine().getStatusCode());
528 BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
530 StringBuffer result = new StringBuffer();
532 while ((line = rd.readLine()) != null) {
536 _log.info("POST response is " + result.toString());
537 return result.toString();
540 private static int sendValuePairPost(String url, List<NameValuePair> urlParameters, String response)
543 HttpClient client = new DefaultHttpClient();
544 HttpPost post = new HttpPost(url);
547 post.setHeader("User-Agent", USER_AGENT);
548 post.setHeader("Content-type", "application/x-www-form-urlencoded");
549 post.setHeader("Authorization", ACCESS_TOKEN);
551 post.setEntity(new UrlEncodedFormEntity(urlParameters));
553 HttpResponse httpResponse = client.execute(post);
555 // _log.info("Sending POST request to URL : " + url);
556 // _log.info("Post parameters : " + post.getEntity());
557 int statusCode = httpResponse.getStatusLine().getStatusCode();
558 // _log.info("Response Code : " + statusCode);
560 BufferedReader rd = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
562 StringBuffer result = new StringBuffer();
564 while ((line = rd.readLine()) != null) {
568 // _log.info("POST response is "+result.toString());
569 response = result.toString();
574 * Send HTTP GET request
577 * @param urlParameters
578 * - the map of parameters
582 private static String sendGet(String url) throws Exception {
584 URL obj = new URL(url);
585 HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
587 // add request header
588 con.setRequestMethod("GET");
589 con.setRequestProperty("User-Agent", USER_AGENT);
590 con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
591 con.setRequestProperty("Authorization", ACCESS_TOKEN);
592 con.setDoOutput(true);
594 _log.info("Sending GET request to URL : " + url);
595 int responseCode = con.getResponseCode();
596 _log.info("Response Code : " + responseCode);
597 if (responseCode != HTTP_CODE_OK) {
602 BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
604 StringBuffer getResponse = new StringBuffer();
605 while ((inputLine = in.readLine()) != null) {
606 getResponse.append(inputLine);
610 return getResponse.toString();
614 * Builds the username in edx, following some constraints
619 private static String buildUserName(User user) {
621 String result = user.getScreenName();
624 result = result.replaceAll(" ", "_");
626 // Remove special characters
627 result = Normalizer.normalize(result, Normalizer.Form.NFD);
628 result = result.replaceAll("[\u0300-\u036F]", "");
630 // a-z,A-Z,0-9 characters only
631 StringBuilder str = new StringBuilder();
632 for (char c : result.toCharArray()) {
633 if (Character.isLetterOrDigit(c) || c == '_') {
637 result = str.toString();
640 if (result.length() > MAX_USERNAME_LENGTH) {
641 result = result.substring(0, MAX_USERNAME_LENGTH - 1);