View Javadoc
1   /*
2    * Copyright (C) 2003-2014 eXo Platform SAS.
3    *
4    * This is free software; you can redistribute it and/or modify it
5    * under the terms of the GNU Lesser General Public License as
6    * published by the Free Software Foundation; either version 3 of
7    * the License, or (at your option) any later version.
8    *
9    * This software is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12   * Lesser General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this software; if not, write to the Free
16   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
18   */
19  package org.exoplatform.utils;
20  
21  import java.io.BufferedReader;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.InputStreamReader;
25  import java.net.HttpURLConnection;
26  import java.util.ArrayList;
27  import java.util.List;
28  
29  import org.apache.http.HttpEntity;
30  import org.apache.http.HttpResponse;
31  import org.apache.http.HttpStatus;
32  import org.apache.http.NameValuePair;
33  import org.apache.http.client.ClientProtocolException;
34  import org.apache.http.client.CookieStore;
35  import org.apache.http.client.entity.UrlEncodedFormEntity;
36  import org.apache.http.client.methods.HttpGet;
37  import org.apache.http.client.methods.HttpPost;
38  import org.apache.http.cookie.Cookie;
39  import org.apache.http.impl.client.BasicCookieStore;
40  import org.apache.http.impl.client.DefaultHttpClient;
41  import org.apache.http.impl.cookie.BasicClientCookie;
42  import org.apache.http.message.BasicNameValuePair;
43  import org.apache.http.params.BasicHttpParams;
44  import org.apache.http.params.HttpConnectionParams;
45  import org.apache.http.params.HttpParams;
46  import org.apache.http.params.HttpProtocolParams;
47  import org.json.simple.JSONObject;
48  import org.json.simple.JSONValue;
49  
50  import org.exoplatform.singleton.AccountSetting;
51  import org.exoplatform.singleton.DocumentHelper;
52  import org.exoplatform.singleton.ServerSettingHelper;
53  import org.exoplatform.singleton.SocialServiceHelper;
54  import org.exoplatform.ui.login.tasks.LogoutTask;
55  import org.exoplatform.utils.image.ExoPicasso;
56  
57  import android.content.Context;
58  import android.net.ConnectivityManager;
59  import android.net.NetworkInfo;
60  
61  //interact with server
62  public class ExoConnectionUtils {
63  
64    public static final int         LOGIN_WRONG                = 0;
65  
66    public static final int         LOGIN_SUCCESS              = 1;
67  
68    public static final int         LOGIN_UNAUTHORIZED         = 2;
69  
70    public static final int         LOGIN_INVALID              = 3;
71  
72    public static final int         LOGIN_FAILED               = 4;
73  
74    public static final int         LOGIN_INCOMPATIBLE         = 5;
75  
76    public static final int         LOGIN_SERVER_RESUMING      = 6;
77  
78    // Default connection and socket timeout of 30 seconds. Tweak to taste.
79    public static final int         SOCKET_OPERATION_TIMEOUT   = 30 * 1000;
80  
81    public static final String      USER_AGENT_KEY             = "User-Agent";
82  
83    private static String           USER_AGENT;
84  
85    public static DefaultHttpClient httpClient;
86  
87    public static CookieStore       cookiesStore;
88  
89    public static final int         SIGNUP_OK                  = 10;
90  
91    /** internal server problem, strange response status code */
92    public static final int         SIGNUP_INVALID             = 11;
93  
94    /** domain for the email is invalid, such as gmail, yahoo ... */
95    public static final int         SIGNUP_WRONG_DOMAIN        = 12;
96  
97    /** an account already exists for this email */
98    public static final int         SIGNUP_ACCOUNT_EXISTS      = 13;
99  
100   /** can not connect server, probably down or wrong address */
101   public static final int         SIGNUP_SERVER_NAV          = 14;
102 
103   /** maximum number of users for the tenant has been reached */
104   public static final int         SIGNUP_MAX_USERS           = 15;
105 
106   private static final String     SIGNUP_MAX_USERS_MSG       = "The request to create or join a workspace from ";
107 
108   public static final int         SIGNIN_OK                  = 20;
109 
110   public static final int         SIGNIN_INVALID             = 21;
111 
112   public static final int         SIGNIN_NO_ACCOUNT          = 22;
113 
114   /** cloud can not find tenant for this email */
115   public static final int         SIGNIN_NO_TENANT_FOR_EMAIL = 23;
116 
117   /** like SIGNUP_SERVER_NAV */
118   public static final int         SIGNIN_SERVER_NAV          = 24;
119 
120   public static final int         SIGNIN_SERVER_ONLINE       = 25;
121 
122   public static final int         SIGNIN_SERVER_SUSPENDED    = 26;
123 
124   public static final int         SIGNIN_CONNECTION_ERR      = 27;
125 
126   public static final int         TENANT_OK                  = 30;
127 
128   /** === Tenant status === */
129   public static final String      ONLINE                     = "ONLINE";
130 
131   public static final String      STOPPED                    = "STOPPED";
132 
133   public static final String      HTTP                       = "http://";
134 
135   public static final String      HTTPS                      = "https://";
136 
137   /** eXo cloud workspace url */
138   public static final String      EXO_CLOUD_WS_DOMAIN        = "exoplatform.net";
139   // "wks-acc.exoplatform.org";
140   // "netstg.exoplatform.org";
141 
142   /** eXo cloud base service url */
143   public static final String      SERVICE_BASE_URL           = "/rest/cloud-admin/cloudworkspaces/tenant-service";
144 
145   public static final String      MARKETO_URL                = "learn.exoplatform.com/index.php/leadCapture/save";
146 
147   private static final String     TAG                        = "ExoConnectionUtils";
148 
149   /**
150    * Check mobile network and wireless status
151    */
152   public static boolean isNetworkAvailableExt(Context paramContext) {
153     ConnectivityManager localConnectivityManager = (ConnectivityManager) paramContext.getSystemService("connectivity");
154     if (localConnectivityManager == null) {
155       return false;
156     }
157     while (true) {
158       //
159       NetworkInfo localNetworkInfo = localConnectivityManager.getActiveNetworkInfo();
160       if ((localNetworkInfo == null) || (localNetworkInfo.getState() != NetworkInfo.State.CONNECTED))
161         return false;
162       if (localNetworkInfo.getType() == 1) {
163         return true;
164       }
165       if (localNetworkInfo.getType() == 0) {
166         return true;
167       }
168       return true;
169     }
170   }
171 
172   // Convert stream to String
173   public static String convertStreamToString(InputStream is) {
174     BufferedReader reader = new BufferedReader(new InputStreamReader(is));
175     StringBuilder sb = new StringBuilder();
176 
177     String line = null;
178     try {
179       while ((line = reader.readLine()) != null) {
180         sb.append(line + "\n");
181       }
182     } catch (IOException e) {
183       if (Log.LOGD)
184         Log.d(ExoConnectionUtils.class.getSimpleName(), e.getMessage(), Log.getStackTraceString(e));
185       return null;
186     } finally {
187       try {
188         is.close();
189       } catch (IOException e) {
190         if (Log.LOGD)
191           Log.d(ExoConnectionUtils.class.getSimpleName(), e.getMessage(), Log.getStackTraceString(e));
192         return null;
193       }
194     }
195     return sb.toString();
196   }
197 
198   /*
199    * check session timeout
200    */
201 
202   public static int checkTimeout(String url) {
203     HttpGet httpGet = new HttpGet(url);
204     try {
205       if (httpClient == null) {
206         httpClient = initHttpClient();
207       }
208       HttpResponse response = httpClient.execute(httpGet);
209       int statusCode = checkPlatformRespose(response);
210       if (statusCode == LOGIN_SUCCESS) {
211         return LOGIN_SUCCESS;
212       } else {
213         String username = AccountSetting.getInstance().getUsername();
214         String password = AccountSetting.getInstance().getPassword();
215         StringBuilder buffer = new StringBuilder(username);
216         buffer.append(":");
217         buffer.append(password);
218         httpGet.setHeader("Authorization", "Basic " + Base64.encodeBytes(buffer.toString().getBytes()));
219         response = httpClient.execute(httpGet);
220         cookiesStore = httpClient.getCookieStore();
221         AccountSetting.getInstance().cookiesList = getCookieList(cookiesStore);
222         return checkPlatformRespose(response);
223       }
224 
225     } catch (IOException e) {
226       if (Log.LOGD)
227         Log.d(ExoConnectionUtils.class.getSimpleName(), e.getMessage(), Log.getStackTraceString(e));
228       return LOGIN_WRONG;
229     } catch (IllegalStateException e) {
230       if (Log.LOGD)
231         Log.d(ExoConnectionUtils.class.getSimpleName(), e.getMessage(), Log.getStackTraceString(e));
232       return LOGIN_INVALID;
233     }
234 
235   }
236 
237   public static final String getUserAgent() {
238     if (USER_AGENT == null) {
239       USER_AGENT = new StringBuilder("eXo/").append(ServerSettingHelper.getInstance().getApplicationVersion())
240                                             .append(" (Android)")
241                                             .toString();
242     }
243     return USER_AGENT;
244   }
245 
246   public static void setUserAgent(HttpURLConnection connection) {
247     if (connection != null) {
248       connection.setDoInput(true);
249       connection.addRequestProperty(USER_AGENT_KEY, getUserAgent());
250     }
251   }
252 
253   public static DefaultHttpClient initHttpClient() {
254     HttpParams httpParameters = new BasicHttpParams();
255     HttpConnectionParams.setConnectionTimeout(httpParameters, SOCKET_OPERATION_TIMEOUT);
256     HttpConnectionParams.setSoTimeout(httpParameters, SOCKET_OPERATION_TIMEOUT);
257     HttpConnectionParams.setTcpNoDelay(httpParameters, true);
258     HttpProtocolParams.setUserAgent(httpParameters, getUserAgent());
259 
260     return new DefaultHttpClient(httpParameters);
261   }
262 
263   public static HttpResponse getRequestResponse(String strUrlRequest) throws IOException {
264     HttpGet httpGet = new HttpGet(strUrlRequest);
265     if (httpClient == null) {
266       httpClient = initHttpClient();
267     }
268 
269     return httpClient.execute(httpGet);
270   }
271 
272   // Get input stream from url
273   public static InputStream sendRequest(HttpResponse response) {
274     if (response != null && response.getStatusLine() != null) {
275       int statusCode = response.getStatusLine().getStatusCode();
276       if (statusCode >= HttpStatus.SC_OK && statusCode < HttpStatus.SC_MULTIPLE_CHOICES) {
277         HttpEntity entity = response.getEntity();
278         if (entity != null) {
279           try {
280             return entity.getContent();
281           } catch (IOException e) {
282             Log.d(TAG, e.getClass().getSimpleName(), e.getMessage());
283           } catch (IllegalStateException e) {
284             Log.d(TAG, e.getClass().getSimpleName(), e.getMessage());
285           }
286         }
287       }
288     }
289     return null;
290   }
291 
292   /*
293    * Get response from platform url
294    */
295   public static HttpResponse getPlatformResponse(String username, String password, String strUrlRequest) throws IOException {
296     if (httpClient == null) {
297       httpClient = initHttpClient();
298     }
299     StringBuilder buffer = new StringBuilder(username);
300     buffer.append(":");
301     buffer.append(password);
302     HttpGet httpGet = new HttpGet(strUrlRequest);
303     httpGet.setHeader("Authorization", "Basic " + Base64.encodeBytes(buffer.toString().getBytes()));
304     HttpResponse response = httpClient.execute(httpGet);
305     cookiesStore = httpClient.getCookieStore();
306     AccountSetting.getInstance().cookiesList = getCookieList(cookiesStore);
307 
308     return response;
309   }
310 
311   /**
312    * Make a Sign up request to eXo cloud
313    * 
314    * @param email
315    */
316   public static HttpResponse makeCloudSignUpRequest(String email) throws IOException {
317     Log.d(TAG, "make cloud sign up request with " + email);
318     if (httpClient == null) {
319       httpClient = initHttpClient();
320     }
321 
322     HttpPost httpPost = new HttpPost(HTTPS + EXO_CLOUD_WS_DOMAIN + SERVICE_BASE_URL + "/signup");
323     List<NameValuePair> requestParameters = new ArrayList<NameValuePair>(1);
324     requestParameters.add(new BasicNameValuePair("user-mail", email));
325     httpPost.setEntity(new UrlEncodedFormEntity(requestParameters));
326     return httpClient.execute(httpPost);
327   }
328 
329   public static int checkSignUpResponse(HttpResponse response, String email) {
330     int statusCode = response.getStatusLine().getStatusCode();
331     Log.d(TAG, "status: " + statusCode);
332     String message = getPLFStream(response);
333     /* code 309 */
334     if (statusCode == ExoConstants.UNKNOWN) {
335       if (response.getLastHeader("Location").getValue().contains("tryagain.jsp"))
336         return ExoConnectionUtils.SIGNUP_WRONG_DOMAIN;
337       else
338         return ExoConnectionUtils.SIGNUP_ACCOUNT_EXISTS;
339     }
340     /* code 202 */// TODO: check CLDINT-1197 if any change to response code
341     else if (statusCode == HttpStatus.SC_ACCEPTED || (statusCode == HttpStatus.SC_INTERNAL_SERVER_ERROR && message != null
342         && message.startsWith(SIGNUP_MAX_USERS_MSG + email)))
343       return ExoConnectionUtils.SIGNUP_MAX_USERS;
344 
345     if (statusCode != HttpStatus.SC_OK)
346       return ExoConnectionUtils.SIGNUP_SERVER_NAV;
347 
348     /* code 200 */
349     return ExoConnectionUtils.SIGNUP_OK;
350   }
351 
352   /**
353    * Request tenant and username for an email
354    * 
355    * @param email
356    * @return
357    * @throws IOException
358    */
359   public static HttpResponse requestTenantForEmail(String email) throws IOException {
360     return getRequestResponse(HTTPS + EXO_CLOUD_WS_DOMAIN + SERVICE_BASE_URL + "/usermailinfo/" + email);
361   }
362 
363   public static String[] checkRequestTenant(HttpResponse response) {
364 
365     String[] results = new String[2];
366     if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
367       return null;
368 
369     try {
370       String result = getPLFStream(response);
371       JSONObject json = (JSONObject) JSONValue.parse(result);
372       results[0] = json.get(ExoConstants.USERNAME).toString();
373       results[1] = json.get(ExoConstants.TENANT).toString();
374       Log.d(TAG, "user:   ", results[0], " - tenant: ", results[1]);
375       return results;
376     } catch (RuntimeException e) {
377       // XXX can not replace because getPLFStream, JSONValue.parse can throw
378       // exceptions.
379       Log.d(TAG, "RuntimeException: ", e.getLocalizedMessage());
380       return null;
381     }
382   }
383 
384   /**
385    * Requesting if username exists within a cloud server
386    * 
387    * @param user
388    * @param tenant
389    * @return
390    */
391   public static boolean requestAccountExistsForUser(String user, String tenant) {
392     String url = HTTPS + EXO_CLOUD_WS_DOMAIN + SERVICE_BASE_URL + "/isuserexist/" + tenant + "/" + user;
393     try {
394       HttpResponse response = getRequestResponse(url);
395       if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
396         return false;
397 
398       return convertStreamToString(response.getEntity().getContent()).replace("\n", "")
399                                                                      .replace("\r", "")
400                                                                      .replace("\r\n", "")
401                                                                      .equalsIgnoreCase("true");
402     } catch (IOException e) {
403       Log.d(TAG, "IOException: " + e.getLocalizedMessage());
404       return false;
405     }
406   }
407 
408   /**
409    * Check status of tenant
410    * 
411    * @param tenant
412    * @return
413    */
414   public static int requestTenantStatus(String tenant) {
415     String url = HTTPS + EXO_CLOUD_WS_DOMAIN + SERVICE_BASE_URL + "/status/" + tenant;
416     try {
417       HttpResponse response = getRequestResponse(url);
418       /** 404 - tenant does not exist */
419       int statusCode = response.getStatusLine().getStatusCode();
420       if (statusCode == HttpStatus.SC_NOT_FOUND)
421         return SIGNIN_NO_TENANT_FOR_EMAIL;
422       if (statusCode != HttpStatus.SC_OK)
423         return SIGNIN_SERVER_NAV;
424 
425       /** 200 - tenant exists - check status */
426       if (response.getEntity() != null) {
427         String tenantStatus = convertStreamToString(response.getEntity().getContent()).replace("\n", "")
428                                                                                       .replace("\r", "")
429                                                                                       .replace("\r\n", "");
430 
431         if (tenantStatus.equalsIgnoreCase(ONLINE))
432           return SIGNIN_SERVER_ONLINE;
433         else if (tenantStatus.equalsIgnoreCase(STOPPED))
434           return SIGNIN_SERVER_SUSPENDED;
435 
436         return LOGIN_SERVER_RESUMING;
437       }
438 
439       return SIGNIN_SERVER_NAV;
440     } catch (IOException e) {
441       Log.d(TAG, "IOException: " + e.getLocalizedMessage());
442       return SIGNIN_SERVER_NAV;
443     }
444   }
445 
446   /**
447    * Create marketo lead
448    */
449   public static HttpResponse requestCreatingMarketo(String email) throws IOException {
450     int idx1 = email.indexOf("@");
451     int idx2 = email.lastIndexOf(".");
452     String tenant = (idx1 > 0 && idx2 > 2) ? email.substring(idx1 + 1, idx2) : "";
453     HttpPost httpPost = new HttpPost(HTTP + MARKETO_URL);
454     List<NameValuePair> requestParameters = new ArrayList<NameValuePair>(1);
455     requestParameters.add(new BasicNameValuePair("Email", email));
456     requestParameters.add(new BasicNameValuePair("eXo_Cloud_Tenant_Name__c", tenant));
457     requestParameters.add(new BasicNameValuePair("lpId", "1967"));
458     requestParameters.add(new BasicNameValuePair("subId", "46"));
459     requestParameters.add(new BasicNameValuePair("munchkinId", "577-PCT-880"));
460     requestParameters.add(new BasicNameValuePair("formid", "1167"));
461     requestParameters.add(new BasicNameValuePair("returnLPId", "-1"));
462     httpPost.setEntity(new UrlEncodedFormEntity(requestParameters));
463     return httpClient.execute(httpPost);
464   }
465 
466   /**
467    * Checking the response status code
468    */
469   public static int checkPlatformRespose(HttpResponse response) {
470     int statusCode = response.getStatusLine().getStatusCode();
471     if (statusCode >= HttpStatus.SC_OK && statusCode < HttpStatus.SC_MULTIPLE_CHOICES) {
472       return LOGIN_SUCCESS;
473     } else if (statusCode == HttpStatus.SC_UNAUTHORIZED) {
474       return LOGIN_UNAUTHORIZED;
475     } else if (statusCode == HttpStatus.SC_NOT_FOUND) {
476       return LOGIN_INVALID;
477     } else if (statusCode == ExoConstants.UNKNOWN) {
478       /* 309 code - server is resuming */
479       return LOGIN_SERVER_RESUMING;
480     } else
481       return LOGIN_FAILED;
482   }
483 
484   // get input stream from URL without authentication
485   public static InputStream sendRequestWithoutAuthen(HttpResponse response) {
486     InputStream ipstr = null;
487     try {
488       HttpEntity entity;
489       entity = response.getEntity();
490       if (entity != null) {
491         ipstr = entity.getContent();
492       }
493     } catch (ClientProtocolException e) {
494       Log.d(TAG, "sendRequestWithoutAuthen", Log.getStackTraceString(e));
495     } catch (IOException e) {
496       Log.d(TAG, "sendRequestWithoutAuthen", Log.getStackTraceString(e));
497     }
498     return ipstr;
499   }
500 
501   // Get string input stream from URL
502   public static String sendRequestAndReturnString(HttpResponse response) {
503     return convertStreamToString(sendRequest(response));
504   }
505 
506   // get the JSONObject string of PLF
507   private static String getPLFStream(HttpResponse response) {
508     return convertStreamToString(sendRequestWithoutAuthen(response));
509   }
510 
511   /*
512    * Check the version of PLF is mobile compatible or not
513    */
514   public static boolean checkPLFVersion(HttpResponse response, String domain, String username) {
515     try {
516 
517       String result = getPLFStream(response);
518       JSONObject json = (JSONObject) JSONValue.parse(result);
519 
520       String isCompliant = json.get(ExoConstants.IS_MOBILE_COMPLIANT).toString();
521       if ("true".equalsIgnoreCase(isCompliant)) {
522         String editionObject = json.get(ExoConstants.PLATFORM_EDITION).toString();
523         ServerSettingHelper.getInstance().setServerEdition(editionObject);
524         String verObject = json.get(ExoConstants.PLATFORM_VERSION).toString();
525         ServerSettingHelper.getInstance().setServerVersion(verObject);
526 
527         /*
528          * Get repository name
529          */
530         String repository = ExoConstants.DOCUMENT_REPOSITORY;
531         if (json.containsKey(ExoConstants.PLATFORM_CURRENT_REPO_NAME)) {
532           repository = json.get(ExoConstants.PLATFORM_CURRENT_REPO_NAME).toString();
533           if (repository == null || "".equals(repository.trim())) {
534             repository = ExoConstants.DOCUMENT_REPOSITORY;
535           }
536         }
537         DocumentHelper.getInstance().repository = repository;
538 
539         /*
540          * Get default workspace name
541          */
542         String workspace = ExoConstants.DOCUMENT_COLLABORATION;
543         if (json.containsKey(ExoConstants.PLATFORM_DEFAULT_WORKSPACE)) {
544           workspace = json.get(ExoConstants.PLATFORM_DEFAULT_WORKSPACE).toString();
545           if (workspace == null || "".equals(workspace.trim()))
546             workspace = ExoConstants.DOCUMENT_COLLABORATION;
547         }
548         DocumentHelper.getInstance().workspace = workspace;
549 
550         String userHomeNode = json.get(ExoConstants.USER_HOME_NODE_PATH).toString();
551         ExoDocumentUtils.setRepositoryHomeUrl(username, userHomeNode, domain);
552         return true;
553       } else
554         return false;
555     } catch (RuntimeException e) {
556       // XXX cannot replace because getPLFStream, JSONValue.parse can throw
557       // exception,
558       return false;
559     }
560 
561   }
562 
563   public static ArrayList<String> getCookieList(CookieStore cookieStore) {
564     ArrayList<String> cookieList = new ArrayList<String>();
565     List<Cookie> cookies = cookieStore.getCookies();
566     String strCookie = "";
567     if (!cookies.isEmpty()) {
568       for (int i = 0; i < cookies.size(); i++) {
569         strCookie = cookies.get(i).getName().toString() + "=" + cookies.get(i).getValue().toString();
570         cookieList.add(strCookie);
571       }
572     }
573     return cookieList;
574   }
575 
576   public static void setCookieStore(CookieStore cookieStore, ArrayList<String> list) {
577     cookieStore = new BasicCookieStore();
578     if (list != null) {
579       for (String cookieStr : list) {
580         String[] keyValue = cookieStr.split("=");
581         String key = keyValue[0];
582         String value = "";
583         if (keyValue.length > 1)
584           value = keyValue[1];
585         cookieStore.addCookie(new BasicClientCookie(key, value));
586       }
587     }
588   }
589 
590   /**
591    * Clean up connection data to log out
592    */
593   public static void loggingOut() {
594     // TODO log out in an async task
595     if (ExoConnectionUtils.httpClient != null) {
596       new LogoutTask(ExoConnectionUtils.httpClient).execute();
597       ExoConnectionUtils.httpClient = null;
598     }
599     // Clear all cached settings about the current account
600     AccountSetting.getInstance().clear();
601     if (ExoConnectionUtils.cookiesStore != null)
602       ExoConnectionUtils.cookiesStore.clear();
603     // Clear the Picasso instance
604     ExoPicasso.clear();
605     // Clear all social service data
606     SocialServiceHelper.getInstance().clearData();
607     // Remove Crashlytics user information
608     CrashUtils.setUsername("");
609     CrashUtils.setServerInfo("", "");
610   }
611 
612 }