001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.util;
016    
017    import com.liferay.portal.events.EventsProcessorUtil;
018    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
019    import com.liferay.portal.kernel.dao.shard.ShardUtil;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.search.SearchEngineUtil;
023    import com.liferay.portal.kernel.util.ArrayUtil;
024    import com.liferay.portal.kernel.util.CookieKeys;
025    import com.liferay.portal.kernel.util.GetterUtil;
026    import com.liferay.portal.kernel.util.HttpUtil;
027    import com.liferay.portal.kernel.util.PropsKeys;
028    import com.liferay.portal.kernel.util.SetUtil;
029    import com.liferay.portal.kernel.util.Validator;
030    import com.liferay.portal.model.Company;
031    import com.liferay.portal.model.Group;
032    import com.liferay.portal.model.LayoutSet;
033    import com.liferay.portal.model.PortletCategory;
034    import com.liferay.portal.model.User;
035    import com.liferay.portal.model.VirtualHost;
036    import com.liferay.portal.security.auth.CompanyThreadLocal;
037    import com.liferay.portal.security.auth.PrincipalThreadLocal;
038    import com.liferay.portal.security.exportimport.UserImporterUtil;
039    import com.liferay.portal.security.ldap.LDAPSettingsUtil;
040    import com.liferay.portal.service.CompanyLocalServiceUtil;
041    import com.liferay.portal.service.GroupLocalServiceUtil;
042    import com.liferay.portal.service.LayoutSetLocalServiceUtil;
043    import com.liferay.portal.service.PortletLocalServiceUtil;
044    import com.liferay.portal.service.UserLocalServiceUtil;
045    import com.liferay.portal.service.VirtualHostLocalServiceUtil;
046    
047    import java.sql.Connection;
048    import java.sql.PreparedStatement;
049    import java.sql.ResultSet;
050    import java.sql.SQLException;
051    
052    import java.util.ArrayList;
053    import java.util.List;
054    import java.util.Set;
055    
056    import javax.servlet.ServletContext;
057    import javax.servlet.http.HttpServletRequest;
058    
059    /**
060     * @author Brian Wing Shun Chan
061     * @author Jose Oliver
062     * @author Atul Patel
063     * @author Mika Koivisto
064     */
065    public class PortalInstances {
066    
067            public static void addCompanyId(long companyId) {
068                    _instance._addCompanyId(companyId);
069            }
070    
071            public static long getCompanyId(HttpServletRequest request) {
072                    return _instance._getCompanyId(request);
073            }
074    
075            public static long[] getCompanyIds() {
076                    return _instance._getCompanyIds();
077            }
078    
079            public static long[] getCompanyIdsBySQL() throws SQLException {
080                    return _instance._getCompanyIdsBySQL();
081            }
082    
083            public static long getDefaultCompanyId() {
084                    return _instance._getDefaultCompanyId();
085            }
086    
087            public static String[] getWebIds() {
088                    return _instance._getWebIds();
089            }
090    
091            public static long initCompany(
092                    ServletContext servletContext, String webId) {
093    
094                    return _instance._initCompany(servletContext, webId);
095            }
096    
097            public static boolean isAutoLoginIgnoreHost(String host) {
098                    return _instance._isAutoLoginIgnoreHost(host);
099            }
100    
101            public static boolean isAutoLoginIgnorePath(String path) {
102                    return _instance._isAutoLoginIgnorePath(path);
103            }
104    
105            public static boolean isCompanyActive(long companyId) {
106                    return _instance._isCompanyActive(companyId);
107            }
108    
109            public static boolean isVirtualHostsIgnoreHost(String host) {
110                    return _instance._isVirtualHostsIgnoreHost(host);
111            }
112    
113            public static boolean isVirtualHostsIgnorePath(String path) {
114                    return _instance._isVirtualHostsIgnorePath(path);
115            }
116    
117            public static void reload(ServletContext servletContext) {
118                    _instance._reload(servletContext);
119            }
120    
121            public static void removeCompany(long companyId) {
122                    _instance._removeCompanyId(companyId);
123            }
124    
125            private PortalInstances() {
126                    _companyIds = new long[0];
127                    _autoLoginIgnoreHosts = SetUtil.fromArray(
128                            PropsUtil.getArray(PropsKeys.AUTO_LOGIN_IGNORE_HOSTS));
129                    _autoLoginIgnorePaths = SetUtil.fromArray(
130                            PropsUtil.getArray(PropsKeys.AUTO_LOGIN_IGNORE_PATHS));
131                    _virtualHostsIgnoreHosts = SetUtil.fromArray(
132                            PropsUtil.getArray(PropsKeys.VIRTUAL_HOSTS_IGNORE_HOSTS));
133                    _virtualHostsIgnorePaths = SetUtil.fromArray(
134                            PropsUtil.getArray(PropsKeys.VIRTUAL_HOSTS_IGNORE_PATHS));
135            }
136    
137            private void _addCompanyId(long companyId) {
138                    if (ArrayUtil.contains(_companyIds, companyId)) {
139                            return;
140                    }
141    
142                    long[] companyIds = new long[_companyIds.length + 1];
143    
144                    System.arraycopy(_companyIds, 0, companyIds, 0, _companyIds.length);
145    
146                    companyIds[_companyIds.length] = companyId;
147    
148                    _companyIds = companyIds;
149            }
150    
151            private long _getCompanyId(HttpServletRequest request) {
152                    if (_log.isDebugEnabled()) {
153                            _log.debug("Get company id");
154                    }
155    
156                    Long companyIdObj = (Long)request.getAttribute(WebKeys.COMPANY_ID);
157    
158                    if (_log.isDebugEnabled()) {
159                            _log.debug("Company id from request " + companyIdObj);
160                    }
161    
162                    if (companyIdObj != null) {
163                            return companyIdObj.longValue();
164                    }
165    
166                    long companyId = _getCompanyIdByVirtualHosts(request);
167    
168                    if (_log.isDebugEnabled()) {
169                            _log.debug("Company id from host " + companyId);
170                    }
171    
172                    if (companyId <= 0) {
173                            long cookieCompanyId = GetterUtil.getLong(
174                                    CookieKeys.getCookie(request, CookieKeys.COMPANY_ID, false));
175    
176                            if (cookieCompanyId > 0) {
177                                    try {
178                                            if (CompanyLocalServiceUtil.fetchCompanyById(
179                                                            cookieCompanyId) == null) {
180    
181                                                    if (_log.isWarnEnabled()) {
182                                                            _log.warn(
183                                                                    "Company id from cookie " + cookieCompanyId +
184                                                                            " does not exist");
185                                                    }
186                                            }
187                                            else {
188                                                    companyId = cookieCompanyId;
189    
190                                                    if (_log.isDebugEnabled()) {
191                                                            _log.debug("Company id from cookie " + companyId);
192                                                    }
193                                            }
194                                    }
195                                    catch (Exception e) {
196                                            _log.error(e, e);
197                                    }
198                            }
199                    }
200    
201                    if (companyId <= 0) {
202                            companyId = _getDefaultCompanyId();
203    
204                            if (_log.isDebugEnabled()) {
205                                    _log.debug("Default company id " + companyId);
206                            }
207                    }
208    
209                    if (_log.isDebugEnabled()) {
210                            _log.debug("Set company id " + companyId);
211                    }
212    
213                    request.setAttribute(WebKeys.COMPANY_ID, new Long(companyId));
214    
215                    CompanyThreadLocal.setCompanyId(companyId);
216    
217                    if (Validator.isNotNull(PropsValues.VIRTUAL_HOSTS_DEFAULT_SITE_NAME) &&
218                            (request.getAttribute(WebKeys.VIRTUAL_HOST_LAYOUT_SET) == null)) {
219    
220                            try {
221                                    Group group = GroupLocalServiceUtil.getGroup(
222                                            companyId, PropsValues.VIRTUAL_HOSTS_DEFAULT_SITE_NAME);
223    
224                                    LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
225                                            group.getGroupId(), false);
226    
227                                    if (Validator.isNull(layoutSet.getVirtualHostname())) {
228                                            request.setAttribute(
229                                                    WebKeys.VIRTUAL_HOST_LAYOUT_SET, layoutSet);
230                                    }
231                            }
232                            catch (Exception e) {
233                                    _log.error(e, e);
234                            }
235                    }
236    
237                    return companyId;
238            }
239    
240            private long _getCompanyIdByVirtualHosts(HttpServletRequest request) {
241                    String host = PortalUtil.getHost(request);
242    
243                    if (_log.isDebugEnabled()) {
244                            _log.debug("Host " + host);
245                    }
246    
247                    if (Validator.isNull(host) || _isVirtualHostsIgnoreHost(host)) {
248                            return 0;
249                    }
250    
251                    try {
252                            VirtualHost virtualHost =
253                                    VirtualHostLocalServiceUtil.fetchVirtualHost(host);
254    
255                            if (virtualHost == null) {
256                                    return 0;
257                            }
258    
259                            if (virtualHost.getLayoutSetId() != 0) {
260                                    LayoutSet layoutSet = null;
261    
262                                    try {
263                                            ShardUtil.pushCompanyService(virtualHost.getCompanyId());
264    
265                                            layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
266                                                    virtualHost.getLayoutSetId());
267                                    }
268                                    finally {
269                                            ShardUtil.popCompanyService();
270                                    }
271    
272                                    if (_log.isDebugEnabled()) {
273                                            _log.debug(
274                                                    "Company " + virtualHost.getCompanyId() +
275                                                            " is associated with layout set " +
276                                                                    virtualHost.getLayoutSetId());
277                                    }
278    
279                                    request.setAttribute(
280                                            WebKeys.VIRTUAL_HOST_LAYOUT_SET, layoutSet);
281                            }
282    
283                            return virtualHost.getCompanyId();
284                    }
285                    catch (Exception e) {
286                            _log.error(e, e);
287                    }
288    
289                    return 0;
290            }
291    
292            private long[] _getCompanyIds() {
293                    return _companyIds;
294            }
295    
296            private long[] _getCompanyIdsBySQL() throws SQLException {
297                    List<Long> companyIds = new ArrayList<>();
298    
299                    String currentShardName = ShardUtil.setTargetSource(
300                            PropsValues.SHARD_DEFAULT_NAME);
301    
302                    if (Validator.isNotNull(currentShardName)) {
303                            ShardUtil.pushCompanyService(PropsValues.SHARD_DEFAULT_NAME);
304                    }
305    
306                    Connection con = null;
307                    PreparedStatement ps = null;
308                    ResultSet rs = null;
309    
310                    try {
311                            con = DataAccess.getConnection();
312    
313                            ps = con.prepareStatement(_GET_COMPANY_IDS);
314    
315                            if (Validator.isNotNull(currentShardName)) {
316                                    ps.setString(1, currentShardName);
317                            }
318                            else {
319                                    ps.setString(1, PropsValues.SHARD_DEFAULT_NAME);
320                            }
321    
322                            rs = ps.executeQuery();
323    
324                            while (rs.next()) {
325                                    long companyId = rs.getLong("companyId");
326    
327                                    companyIds.add(companyId);
328                            }
329                    }
330                    finally {
331                            if (Validator.isNotNull(currentShardName)) {
332                                    ShardUtil.popCompanyService();
333    
334                                    ShardUtil.setTargetSource(currentShardName);
335                            }
336    
337                            DataAccess.cleanUp(con, ps, rs);
338                    }
339    
340                    return ArrayUtil.toArray(
341                            companyIds.toArray(new Long[companyIds.size()]));
342            }
343    
344            private long _getDefaultCompanyId() {
345                    return _companyIds[0];
346            }
347    
348            private String[] _getWebIds() {
349                    if (_webIds != null) {
350                            return _webIds;
351                    }
352    
353                    if (Validator.isNull(PropsValues.COMPANY_DEFAULT_WEB_ID)) {
354                            throw new RuntimeException("Default web id must not be null");
355                    }
356    
357                    try {
358                            List<Company> companies = CompanyLocalServiceUtil.getCompanies(
359                                    false);
360    
361                            List<String> webIdsList = new ArrayList<>(companies.size());
362    
363                            for (Company company : companies) {
364                                    String webId = company.getWebId();
365    
366                                    if (webId.equals(PropsValues.COMPANY_DEFAULT_WEB_ID)) {
367                                            webIdsList.add(0, webId);
368                                    }
369                                    else {
370                                            webIdsList.add(webId);
371                                    }
372                            }
373    
374                            _webIds = webIdsList.toArray(new String[webIdsList.size()]);
375                    }
376                    catch (Exception e) {
377                            _log.error(e, e);
378                    }
379    
380                    if (ArrayUtil.isEmpty(_webIds)) {
381                            _webIds = new String[] {PropsValues.COMPANY_DEFAULT_WEB_ID};
382                    }
383    
384                    return _webIds;
385            }
386    
387            private long _initCompany(ServletContext servletContext, String webId) {
388    
389                    // Begin initializing company
390    
391                    if (_log.isDebugEnabled()) {
392                            _log.debug("Begin initializing company with web id " + webId);
393                    }
394    
395                    long companyId = 0;
396    
397                    try {
398                            Company company = CompanyLocalServiceUtil.checkCompany(webId);
399    
400                            companyId = company.getCompanyId();
401                    }
402                    catch (Exception e) {
403                            _log.error(e, e);
404                    }
405    
406                    Long currentThreadCompanyId = CompanyThreadLocal.getCompanyId();
407    
408                    String currentThreadPrincipalName = PrincipalThreadLocal.getName();
409    
410                    try {
411                            CompanyThreadLocal.setCompanyId(companyId);
412    
413                            String principalName = null;
414    
415                            try {
416                                    User user = UserLocalServiceUtil.getUser(
417                                            PrincipalThreadLocal.getUserId());
418    
419                                    if (user.getCompanyId() == companyId) {
420                                            principalName = currentThreadPrincipalName;
421                                    }
422                            }
423                            catch (Exception e) {
424                            }
425    
426                            PrincipalThreadLocal.setName(principalName);
427    
428                            // Initialize display
429    
430                            if (_log.isDebugEnabled()) {
431                                    _log.debug("Initialize display");
432                            }
433    
434                            try {
435                                    String xml = HttpUtil.URLtoString(
436                                            servletContext.getResource("/WEB-INF/liferay-display.xml"));
437    
438                                    PortletCategory portletCategory = (PortletCategory)
439                                            WebAppPool.get(companyId, WebKeys.PORTLET_CATEGORY);
440    
441                                    if (portletCategory == null) {
442                                            portletCategory = new PortletCategory();
443                                    }
444    
445                                    PortletCategory newPortletCategory =
446                                            PortletLocalServiceUtil.getEARDisplay(xml);
447    
448                                    portletCategory.merge(newPortletCategory);
449    
450                                    for (int i = 0; i < _companyIds.length; i++) {
451                                            long currentCompanyId = _companyIds[i];
452    
453                                            PortletCategory currentPortletCategory =
454                                                    (PortletCategory)WebAppPool.get(
455                                                            currentCompanyId, WebKeys.PORTLET_CATEGORY);
456    
457                                            if (currentPortletCategory != null) {
458                                                    portletCategory.merge(currentPortletCategory);
459                                            }
460                                    }
461    
462                                    WebAppPool.put(
463                                            companyId, WebKeys.PORTLET_CATEGORY, portletCategory);
464                            }
465                            catch (Exception e) {
466                                    _log.error(e, e);
467                            }
468    
469                            // LDAP import
470    
471                            try {
472                                    if (LDAPSettingsUtil.isImportOnStartup(companyId)) {
473                                            UserImporterUtil.importUsers(companyId);
474                                    }
475                            }
476                            catch (Exception e) {
477                                    _log.error(e, e);
478                            }
479    
480                            // Process application startup events
481    
482                            if (_log.isDebugEnabled()) {
483                                    _log.debug("Process application startup events");
484                            }
485    
486                            try {
487                                    EventsProcessorUtil.process(
488                                            PropsKeys.APPLICATION_STARTUP_EVENTS,
489                                            PropsValues.APPLICATION_STARTUP_EVENTS,
490                                            new String[] {String.valueOf(companyId)});
491                            }
492                            catch (Exception e) {
493                                    _log.error(e, e);
494                            }
495    
496                            // End initializing company
497    
498                            if (_log.isDebugEnabled()) {
499                                    _log.debug(
500                                            "End initializing company with web id " + webId +
501                                                    " and company id " + companyId);
502                            }
503    
504                            addCompanyId(companyId);
505                    }
506                    finally {
507                            CompanyThreadLocal.setCompanyId(currentThreadCompanyId);
508    
509                            PrincipalThreadLocal.setName(currentThreadPrincipalName);
510                    }
511    
512                    return companyId;
513            }
514    
515            private boolean _isAutoLoginIgnoreHost(String host) {
516                    return _autoLoginIgnoreHosts.contains(host);
517            }
518    
519            private boolean _isAutoLoginIgnorePath(String path) {
520                    return _autoLoginIgnorePaths.contains(path);
521            }
522    
523            private boolean _isCompanyActive(long companyId) {
524                    try {
525                            Company company = CompanyLocalServiceUtil.fetchCompanyById(
526                                    companyId);
527    
528                            if (company != null) {
529                                    return company.isActive();
530                            }
531                    }
532                    catch (Exception e) {
533                            _log.error(e, e);
534                    }
535    
536                    return false;
537            }
538    
539            private boolean _isVirtualHostsIgnoreHost(String host) {
540                    return _virtualHostsIgnoreHosts.contains(host);
541            }
542    
543            private boolean _isVirtualHostsIgnorePath(String path) {
544                    return _virtualHostsIgnorePaths.contains(path);
545            }
546    
547            private void _reload(ServletContext servletContext) {
548                    _companyIds = new long[0];
549                    _webIds = null;
550    
551                    String[] webIds = _getWebIds();
552    
553                    for (String webId : webIds) {
554                            _initCompany(servletContext, webId);
555                    }
556            }
557    
558            private void _removeCompanyId(long companyId) {
559                    _companyIds = ArrayUtil.remove(_companyIds, companyId);
560                    _webIds = null;
561    
562                    _getWebIds();
563    
564                    SearchEngineUtil.removeCompany(companyId);
565    
566                    WebAppPool.remove(companyId, WebKeys.PORTLET_CATEGORY);
567            }
568    
569            private static final String _GET_COMPANY_IDS =
570                    "select companyId from Company, Shard where Company.companyId = " +
571                            "Shard.classPK and Shard.name = ?";
572    
573            private static final Log _log = LogFactoryUtil.getLog(
574                    PortalInstances.class);
575    
576            private static final PortalInstances _instance = new PortalInstances();
577    
578            private final Set<String> _autoLoginIgnoreHosts;
579            private final Set<String> _autoLoginIgnorePaths;
580            private long[] _companyIds;
581            private final Set<String> _virtualHostsIgnoreHosts;
582            private final Set<String> _virtualHostsIgnorePaths;
583            private String[] _webIds;
584    
585    }