1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.googleapps;
24  
25  import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
26  import com.liferay.portal.kernel.log.Log;
27  import com.liferay.portal.kernel.log.LogFactoryUtil;
28  import com.liferay.portal.kernel.servlet.HttpHeaders;
29  import com.liferay.portal.kernel.util.ContentTypes;
30  import com.liferay.portal.kernel.util.Http;
31  import com.liferay.portal.kernel.util.HttpUtil;
32  import com.liferay.portal.kernel.util.PropertiesUtil;
33  import com.liferay.portal.kernel.util.PropsKeys;
34  import com.liferay.portal.kernel.util.StringPool;
35  import com.liferay.portal.kernel.util.Time;
36  import com.liferay.portal.kernel.xml.Document;
37  import com.liferay.portal.kernel.xml.Element;
38  import com.liferay.portal.kernel.xml.Namespace;
39  import com.liferay.portal.kernel.xml.QName;
40  import com.liferay.portal.kernel.xml.SAXReaderUtil;
41  import com.liferay.portal.model.Company;
42  import com.liferay.portal.service.CompanyLocalServiceUtil;
43  import com.liferay.portal.util.PrefsPropsUtil;
44  
45  import java.util.Properties;
46  
47  /**
48   * <a href="GoogleApps.java.html"><b><i>View Source</i></b></a>
49   *
50   * @author Brian Wing Shun Chan
51   */
52  public class GoogleApps {
53  
54      public GoogleApps(long companyId) {
55          try {
56              _companyId = companyId;
57  
58              init(true);
59          }
60          catch (Exception e) {
61              _log.error(e, e);
62          }
63      }
64  
65      public void addNickname(long userId, String nickname) throws Exception {
66          Document document = SAXReaderUtil.createDocument();
67  
68          Element atomEntry = _addAtomEntry(document);
69  
70          _addAtomCategory(atomEntry, "nickname");
71  
72          Element appsLogin = atomEntry.addElement("apps:login");
73  
74          appsLogin.addAttribute("userName", String.valueOf(userId));
75  
76          Element appsNickname = atomEntry.addElement("apps:nickname");
77  
78          appsNickname.addAttribute("name", nickname);
79  
80          Http.Options options = _getOptions();
81  
82          options.setBody(
83              document.formattedString(), ContentTypes.APPLICATION_ATOM_XML,
84              StringPool.UTF8);
85          options.setLocation(_getNicknameURL());
86          options.setPost(true);
87  
88          HttpUtil.URLtoString(options);
89      }
90  
91      public void addSendAs(long userId, String fullName, String emailAddress)
92          throws Exception {
93  
94          Document document = SAXReaderUtil.createDocument();
95  
96          Element atomEntry = _addAtomEntry(document);
97  
98          _addAppsProperty(atomEntry, "name", fullName);
99          _addAppsProperty(atomEntry, "address", emailAddress);
100         _addAppsProperty(atomEntry, "makeDefault", Boolean.TRUE.toString());
101 
102         Http.Options options = _getOptions();
103 
104         options.setBody(
105             document.formattedString(), ContentTypes.APPLICATION_ATOM_XML,
106             StringPool.UTF8);
107         options.setLocation(
108             _URL + "emailsettings/2.0/" + _domain + "/" + userId + "/sendas");
109         options.setPost(true);
110 
111         HttpUtil.URLtoString(options);
112     }
113 
114     public void addUser(
115             long userId, String password, String firstName, String lastName)
116         throws Exception {
117 
118         Document document = SAXReaderUtil.createDocument();
119 
120         Element atomEntry = _addAtomEntry(document);
121 
122         _addAtomCategory(atomEntry, "user");
123 
124         Element appsLogin = atomEntry.addElement("apps:login");
125 
126         appsLogin.addAttribute("password", password);
127         appsLogin.addAttribute("userName", String.valueOf(userId));
128 
129         Element appsName = atomEntry.addElement("apps:name");
130 
131         appsName.addAttribute("familyName", lastName);
132         appsName.addAttribute("givenName", firstName);
133 
134         Http.Options options = _getOptions();
135 
136         options.setBody(
137             document.formattedString(), ContentTypes.APPLICATION_ATOM_XML,
138             StringPool.UTF8);
139         options.setLocation(_getUserURL());
140         options.setPost(true);
141 
142         HttpUtil.URLtoString(options);
143     }
144 
145     public void deleteNickname(String nickname) throws Exception {
146         Http.Options options = _getOptions();
147 
148         options.setDelete(true);
149         options.setLocation(_getNicknameURL(nickname));
150 
151         HttpUtil.URLtoString(options);
152     }
153 
154     public void deleteUser(long userId) throws Exception {
155         Http.Options options = _getOptions();
156 
157         options.setDelete(true);
158         options.setLocation(_getUserURL(userId));
159 
160         HttpUtil.URLtoString(options);
161     }
162 
163     public void init(boolean manual) throws Exception {
164         if (manual || _isStale()) {
165             _init();
166         }
167     }
168 
169     public void updatePassword(long userId, String password) throws Exception {
170         String userXML = _getUserXML(userId);
171 
172         Document document = SAXReaderUtil.read(new UnsyncStringReader(userXML));
173 
174         Element atomEntry = document.getRootElement();
175 
176         Element appsLogin = atomEntry.element(_getAppsQName("login"));
177 
178         appsLogin.addAttribute("password", password);
179 
180         Http.Options options = _getOptions();
181 
182         options.setBody(
183             document.formattedString(), ContentTypes.APPLICATION_ATOM_XML,
184             StringPool.UTF8);
185         options.setLocation(_getUserURL(userId));
186         options.setPut(true);
187 
188         HttpUtil.URLtoString(options);
189     }
190 
191     private Element _addAppsProperty(
192         Element parentElement, String name, String value) {
193 
194         Element element = parentElement.addElement("apps:property");
195 
196         element.addAttribute("name", name);
197         element.addAttribute("value", value);
198 
199         return element;
200     }
201 
202     private Element _addAtomCategory(Element parentElement, String type) {
203         Element element = parentElement.addElement("atom:category");
204 
205         element.addAttribute("scheme", "http://schemas.google.com/g/2005#kind");
206         element.addAttribute(
207             "term", "http://schemas.google.com/apps/2006#" + type);
208 
209         return element;
210     }
211 
212     private Element _addAtomEntry(Document document) {
213         Element element = document.addElement("atom:entry");
214 
215         element.add(_getAppsNamespace());
216         element.add(_getAtomNamespace());
217 
218         return element;
219     }
220 
221     private Namespace _getAppsNamespace() {
222         return SAXReaderUtil.createNamespace(_APPS_PREFIX, _APPS_URI);
223     }
224 
225     private QName _getAppsQName(String localName) {
226         return SAXReaderUtil.createQName(localName, _getAppsNamespace());
227     }
228 
229     private Namespace _getAtomNamespace() {
230         return SAXReaderUtil.createNamespace(_ATOM_PREFIX, _ATOM_URI);
231     }
232 
233     private String _getNicknameURL() {
234         return _URL + _domain + "/nickname/2.0";
235     }
236 
237     private String _getNicknameURL(String nickname) {
238         return _getNicknameURL() + StringPool.SLASH + nickname;
239     }
240 
241     private Http.Options _getOptions() {
242         Http.Options options = new Http.Options();
243 
244         options.addHeader(
245             HttpHeaders.AUTHORIZATION,
246             "GoogleLogin auth=" + _authenticationToken);
247 
248         return options;
249     }
250 
251     private String _getUserURL() {
252         return _URL + _domain + "/user/2.0";
253     }
254 
255     private String _getUserURL(long userId) {
256         return _getUserURL() + StringPool.SLASH + userId;
257     }
258 
259     private String _getUserXML(long userId) throws Exception {
260         Http.Options options = _getOptions();
261 
262         options.setLocation(_getUserURL(userId));
263 
264         return HttpUtil.URLtoString(options);
265     }
266 
267     private void _init() throws Exception {
268         Company company = CompanyLocalServiceUtil.getCompany(_companyId);
269 
270         _domain = company.getMx();
271         _userName = PrefsPropsUtil.getString(
272             _companyId, PropsKeys.GOOGLE_APPS_USERNAME);
273         _password = PrefsPropsUtil.getString(
274             _companyId, PropsKeys.GOOGLE_APPS_PASSWORD);
275 
276         if (!_userName.contains(StringPool.AT)) {
277             _userName += StringPool.AT + _domain;
278         }
279 
280         Http.Options options = new Http.Options();
281 
282         options.addPart("Email", _userName);
283         options.addPart("Passwd", _password);
284         options.addPart("accountType", "HOSTED");
285         options.addPart("service", "apps");
286         options.setLocation("https://www.google.com/accounts/ClientLogin");
287         options.setPost(true);
288 
289         String content = HttpUtil.URLtoString(options);
290 
291         Properties properties = PropertiesUtil.load(content);
292 
293         _authenticationToken = properties.getProperty("Auth");
294 
295         _initTime = System.currentTimeMillis();
296     }
297 
298     private boolean _isStale() {
299         if ((_initTime + (Time.HOUR * 23)) > System.currentTimeMillis()) {
300             return false;
301         }
302         else {
303             return true;
304         }
305     }
306 
307     private static final String _APPS_PREFIX = "apps";
308 
309     private static final String _APPS_URI =
310         "http://schemas.google.com/apps/2006";
311 
312     private static final String _ATOM_PREFIX = "atom";
313 
314     private static final String _ATOM_URI = "http://www.w3.org/2005/Atom";
315 
316     private static final String _URL = "https://apps-apis.google.com/a/feeds/";
317 
318     private static Log _log = LogFactoryUtil.getLog(GoogleApps.class);
319 
320     private String _authenticationToken;
321     private long _companyId;
322     private String _domain;
323     private long _initTime;
324     private String _password;
325     private String _userName;
326 
327 }