001    /**
002     * Copyright (c) 2000-2013 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.service.impl;
016    
017    import com.liferay.portal.AccountNameException;
018    import com.liferay.portal.CompanyMxException;
019    import com.liferay.portal.CompanyVirtualHostException;
020    import com.liferay.portal.CompanyWebIdException;
021    import com.liferay.portal.LocaleException;
022    import com.liferay.portal.NoSuchShardException;
023    import com.liferay.portal.NoSuchUserException;
024    import com.liferay.portal.NoSuchVirtualHostException;
025    import com.liferay.portal.kernel.exception.PortalException;
026    import com.liferay.portal.kernel.exception.SystemException;
027    import com.liferay.portal.kernel.language.LanguageUtil;
028    import com.liferay.portal.kernel.log.Log;
029    import com.liferay.portal.kernel.log.LogFactoryUtil;
030    import com.liferay.portal.kernel.search.FacetedSearcher;
031    import com.liferay.portal.kernel.search.Hits;
032    import com.liferay.portal.kernel.search.Indexer;
033    import com.liferay.portal.kernel.search.SearchContext;
034    import com.liferay.portal.kernel.search.SearchEngineUtil;
035    import com.liferay.portal.kernel.search.facet.AssetEntriesFacet;
036    import com.liferay.portal.kernel.search.facet.Facet;
037    import com.liferay.portal.kernel.search.facet.ScopeFacet;
038    import com.liferay.portal.kernel.util.ArrayUtil;
039    import com.liferay.portal.kernel.util.Base64;
040    import com.liferay.portal.kernel.util.LocaleUtil;
041    import com.liferay.portal.kernel.util.PropsKeys;
042    import com.liferay.portal.kernel.util.StringPool;
043    import com.liferay.portal.kernel.util.StringUtil;
044    import com.liferay.portal.kernel.util.TimeZoneUtil;
045    import com.liferay.portal.kernel.util.UnicodeProperties;
046    import com.liferay.portal.kernel.util.Validator;
047    import com.liferay.portal.kernel.workflow.WorkflowConstants;
048    import com.liferay.portal.model.Account;
049    import com.liferay.portal.model.Company;
050    import com.liferay.portal.model.CompanyConstants;
051    import com.liferay.portal.model.Contact;
052    import com.liferay.portal.model.ContactConstants;
053    import com.liferay.portal.model.Group;
054    import com.liferay.portal.model.LayoutSetPrototype;
055    import com.liferay.portal.model.Role;
056    import com.liferay.portal.model.RoleConstants;
057    import com.liferay.portal.model.User;
058    import com.liferay.portal.model.VirtualHost;
059    import com.liferay.portal.service.base.CompanyLocalServiceBaseImpl;
060    import com.liferay.portal.util.Portal;
061    import com.liferay.portal.util.PortalInstances;
062    import com.liferay.portal.util.PrefsPropsUtil;
063    import com.liferay.portal.util.PropsUtil;
064    import com.liferay.portal.util.PropsValues;
065    import com.liferay.util.Encryptor;
066    import com.liferay.util.EncryptorException;
067    
068    import java.io.File;
069    import java.io.IOException;
070    import java.io.InputStream;
071    
072    import java.util.ArrayList;
073    import java.util.Date;
074    import java.util.List;
075    import java.util.Locale;
076    import java.util.Map;
077    import java.util.TimeZone;
078    
079    import javax.portlet.PortletException;
080    import javax.portlet.PortletPreferences;
081    
082    /**
083     * The implementation of the company local service. Each company refers to a
084     * separate portal instance.
085     *
086     * @author Brian Wing Shun Chan
087     * @author Julio Camarero
088     */
089    public class CompanyLocalServiceImpl extends CompanyLocalServiceBaseImpl {
090    
091            /**
092             * Adds a company.
093             *
094             * @param  webId the the company's web domain
095             * @param  virtualHostname the company's virtual host name
096             * @param  mx the company's mail domain
097             * @param  shardName the company's shard
098             * @param  system whether the company is the very first company (i.e., the
099             *         super company)
100             * @param  maxUsers the max number of company users (optionally
101             *         <code>0</code>)
102             * @param  active whether the company is active
103             * @return the company
104             * @throws PortalException if the web domain, virtual host name, or mail
105             *         domain was invalid
106             * @throws SystemException if a system exception occurred
107             */
108            @Override
109            public Company addCompany(
110                            String webId, String virtualHostname, String mx, String shardName,
111                            boolean system, int maxUsers, boolean active)
112                    throws PortalException, SystemException {
113    
114                    // Company
115    
116                    virtualHostname = virtualHostname.trim().toLowerCase();
117    
118                    if (Validator.isNull(webId) ||
119                            webId.equals(PropsValues.COMPANY_DEFAULT_WEB_ID) ||
120                            (companyPersistence.fetchByWebId(webId) != null)) {
121    
122                            throw new CompanyWebIdException();
123                    }
124    
125                    validate(webId, virtualHostname, mx);
126    
127                    Company company = checkCompany(webId, mx, shardName);
128    
129                    company.setMx(mx);
130                    company.setSystem(system);
131                    company.setMaxUsers(maxUsers);
132                    company.setActive(active);
133    
134                    companyPersistence.update(company, false);
135    
136                    // Virtual host
137    
138                    updateVirtualHost(company.getCompanyId(), virtualHostname);
139    
140                    return company;
141            }
142    
143            /**
144             * Returns the company with the web domain.
145             *
146             * The method sets mail domain to the web domain, and the shard name to
147             * the default name set in portal.properties
148             *
149             * @param  webId the company's web domain
150             * @return the company with the web domain
151             * @throws PortalException if a portal exception occurred
152             * @throws SystemException if a system exception occurred
153             */
154            @Override
155            public Company checkCompany(String webId)
156                    throws PortalException, SystemException {
157    
158                    String mx = webId;
159    
160                    return companyLocalService.checkCompany(
161                            webId, mx, PropsValues.SHARD_DEFAULT_NAME);
162            }
163    
164            /**
165             * Returns the company with the web domain, mail domain, and shard. If no
166             * such company exits, the method will create a new company.
167             *
168             * The method goes through a series of checks to ensure that the company
169             * contains default users, groups, etc.
170             *
171             * @param  webId the company's web domain
172             * @param  mx the company's mail domain
173             * @param  shardName the company's shard
174             * @return the company with the web domain, mail domain, and shard
175             * @throws PortalException if a portal exception occurred
176             * @throws SystemException if a system exception occurred
177             */
178            @Override
179            public Company checkCompany(String webId, String mx, String shardName)
180                    throws PortalException, SystemException {
181    
182                    // Company
183    
184                    Date now = new Date();
185    
186                    Company company = companyPersistence.fetchByWebId(webId);
187    
188                    if (company == null) {
189                            long companyId = counterLocalService.increment();
190    
191                            company = companyPersistence.create(companyId);
192    
193                            try {
194                                    company.setKey(Base64.objectToString(Encryptor.generateKey()));
195                            }
196                            catch (EncryptorException ee) {
197                                    throw new SystemException(ee);
198                            }
199    
200                            company.setWebId(webId);
201                            company.setMx(mx);
202                            company.setActive(true);
203    
204                            companyPersistence.update(company, false);
205    
206                            // Shard
207    
208                            shardLocalService.addShard(
209                                    Company.class.getName(), companyId, shardName);
210    
211                            // Account
212    
213                            String name = webId;
214    
215                            if (webId.equals(PropsValues.COMPANY_DEFAULT_WEB_ID)) {
216                                    name = PropsValues.COMPANY_DEFAULT_NAME;
217                            }
218    
219                            String legalName = null;
220                            String legalId = null;
221                            String legalType = null;
222                            String sicCode = null;
223                            String tickerSymbol = null;
224                            String industry = null;
225                            String type = null;
226                            String size = null;
227    
228                            updateAccount(
229                                    company, name, legalName, legalId, legalType, sicCode,
230                                    tickerSymbol, industry, type, size);
231    
232                            // Virtual host
233    
234                            if (webId.equals(PropsValues.COMPANY_DEFAULT_WEB_ID)) {
235                                    updateVirtualHost(companyId, _DEFAULT_VIRTUAL_HOST);
236                            }
237    
238                            // Demo settings
239    
240                            if (webId.equals("liferay.net")) {
241                                    company = companyPersistence.findByWebId(webId);
242    
243                                    updateVirtualHost(companyId, "demo.liferay.net");
244    
245                                    updateSecurity(
246                                            companyId, CompanyConstants.AUTH_TYPE_EA, true, true, true,
247                                            true, false, true);
248    
249                                    PortletPreferences preferences = PrefsPropsUtil.getPreferences(
250                                            companyId);
251    
252                                    try {
253                                            preferences.setValue(
254                                                    PropsKeys.ADMIN_EMAIL_FROM_NAME, "Liferay Demo");
255                                            preferences.setValue(
256                                                    PropsKeys.ADMIN_EMAIL_FROM_ADDRESS, "test@liferay.net");
257    
258                                            preferences.store();
259                                    }
260                                    catch (IOException ioe) {
261                                            throw new SystemException(ioe);
262                                    }
263                                    catch (PortletException pe) {
264                                            throw new SystemException(pe);
265                                    }
266                            }
267                    }
268                    else {
269                            try {
270                                    shardLocalService.getShard(
271                                            Company.class.getName(), company.getCompanyId());
272                            }
273                            catch (NoSuchShardException nsse) {
274                                    shardLocalService.addShard(
275                                            Company.class.getName(), company.getCompanyId(), shardName);
276                            }
277                    }
278    
279                    long companyId = company.getCompanyId();
280    
281                    // Key
282    
283                    checkCompanyKey(companyId);
284    
285                    // Default user
286    
287                    User defaultUser = null;
288    
289                    try {
290                            defaultUser = userLocalService.getDefaultUser(companyId);
291    
292                            if (!defaultUser.isAgreedToTermsOfUse()) {
293                                    defaultUser.setAgreedToTermsOfUse(true);
294    
295                                    userPersistence.update(defaultUser, false);
296                            }
297                    }
298                    catch (NoSuchUserException nsue) {
299                            long userId = counterLocalService.increment();
300    
301                            defaultUser = userPersistence.create(userId);
302    
303                            defaultUser.setCompanyId(companyId);
304                            defaultUser.setCreateDate(now);
305                            defaultUser.setModifiedDate(now);
306                            defaultUser.setDefaultUser(true);
307                            defaultUser.setContactId(counterLocalService.increment());
308                            defaultUser.setPassword("password");
309                            defaultUser.setScreenName(String.valueOf(defaultUser.getUserId()));
310                            defaultUser.setEmailAddress("default@" + company.getMx());
311    
312                            if (Validator.isNotNull(PropsValues.COMPANY_DEFAULT_LOCALE)) {
313                                    defaultUser.setLanguageId(PropsValues.COMPANY_DEFAULT_LOCALE);
314                            }
315                            else {
316                                    Locale locale = LocaleUtil.getDefault();
317    
318                                    defaultUser.setLanguageId(locale.toString());
319                            }
320    
321                            if (Validator.isNotNull(PropsValues.COMPANY_DEFAULT_TIME_ZONE)) {
322                                    defaultUser.setTimeZoneId(
323                                            PropsValues.COMPANY_DEFAULT_TIME_ZONE);
324                            }
325                            else {
326                                    TimeZone timeZone = TimeZoneUtil.getDefault();
327    
328                                    defaultUser.setTimeZoneId(timeZone.getID());
329                            }
330    
331                            defaultUser.setGreeting(
332                                    LanguageUtil.format(
333                                            defaultUser.getLocale(), "welcome-x", StringPool.BLANK,
334                                            false));
335                            defaultUser.setLoginDate(now);
336                            defaultUser.setFailedLoginAttempts(0);
337                            defaultUser.setAgreedToTermsOfUse(true);
338                            defaultUser.setStatus(WorkflowConstants.STATUS_APPROVED);
339    
340                            userPersistence.update(defaultUser, false);
341    
342                            // Contact
343    
344                            Contact defaultContact = contactPersistence.create(
345                                    defaultUser.getContactId());
346    
347                            defaultContact.setCompanyId(defaultUser.getCompanyId());
348                            defaultContact.setUserId(defaultUser.getUserId());
349                            defaultContact.setUserName(StringPool.BLANK);
350                            defaultContact.setCreateDate(now);
351                            defaultContact.setModifiedDate(now);
352                            defaultContact.setAccountId(company.getAccountId());
353                            defaultContact.setParentContactId(
354                                    ContactConstants.DEFAULT_PARENT_CONTACT_ID);
355                            defaultContact.setFirstName(StringPool.BLANK);
356                            defaultContact.setMiddleName(StringPool.BLANK);
357                            defaultContact.setLastName(StringPool.BLANK);
358                            defaultContact.setMale(true);
359                            defaultContact.setBirthday(now);
360    
361                            contactPersistence.update(defaultContact, false);
362                    }
363    
364                    // System roles
365    
366                    roleLocalService.checkSystemRoles(companyId);
367    
368                    // System groups
369    
370                    groupLocalService.checkSystemGroups(companyId);
371    
372                    // Company group
373    
374                    groupLocalService.checkCompanyGroup(companyId);
375    
376                    // Default password policy
377    
378                    passwordPolicyLocalService.checkDefaultPasswordPolicy(companyId);
379    
380                    // Default user must have the Guest role
381    
382                    Role guestRole = roleLocalService.getRole(
383                            companyId, RoleConstants.GUEST);
384    
385                    roleLocalService.setUserRoles(
386                            defaultUser.getUserId(), new long[] {guestRole.getRoleId()});
387    
388                    // Default admin
389    
390                    if (userPersistence.countByCompanyId(companyId) == 1) {
391                            String emailAddress =
392                                    PropsValues.DEFAULT_ADMIN_EMAIL_ADDRESS_PREFIX + "@" + mx;
393    
394                            userLocalService.addDefaultAdminUser(
395                                    companyId, PropsValues.DEFAULT_ADMIN_SCREEN_NAME, emailAddress,
396                                    defaultUser.getLocale(), PropsValues.DEFAULT_ADMIN_FIRST_NAME,
397                                    PropsValues.DEFAULT_ADMIN_MIDDLE_NAME,
398                                    PropsValues.DEFAULT_ADMIN_LAST_NAME);
399                    }
400    
401                    // Portlets
402    
403                    portletLocalService.checkPortlets(companyId);
404    
405                    return company;
406            }
407    
408            /**
409             * Checks if the company has an encryption key. It will create a key if one
410             * does not exist.
411             *
412             * @param  companyId the primary key of the company
413             * @throws PortalException if a company with the primary key could not be
414             *         found
415             * @throws SystemException if a system exception occurred
416             */
417            @Override
418            public void checkCompanyKey(long companyId)
419                    throws PortalException, SystemException {
420    
421                    Company company = companyPersistence.findByPrimaryKey(companyId);
422    
423                    if (Validator.isNull(company.getKey()) &&
424                            (company.getKeyObj() == null)) {
425    
426                            try {
427                                    company.setKey(Base64.objectToString(Encryptor.generateKey()));
428                            }
429                            catch (EncryptorException ee) {
430                                    throw new SystemException(ee);
431                            }
432    
433                            companyPersistence.update(company, false);
434                    }
435            }
436    
437            /**
438             * Deletes the company's logo.
439             *
440             * @param  companyId the primary key of the company
441             * @throws PortalException if the company with the primary key could not be
442             *         found or if the company's logo could not be found
443             * @throws SystemException if a system exception occurred
444             */
445            @Override
446            public void deleteLogo(long companyId)
447                    throws PortalException, SystemException {
448    
449                    Company company = companyPersistence.findByPrimaryKey(companyId);
450    
451                    long logoId = company.getLogoId();
452    
453                    if (logoId > 0) {
454                            company.setLogoId(0);
455    
456                            companyPersistence.update(company, false);
457    
458                            imageLocalService.deleteImage(logoId);
459                    }
460            }
461    
462            /**
463             * Returns the company with the primary key.
464             *
465             * @param  companyId the primary key of the company
466             * @return the company with the primary key, <code>null</code> if a company
467             *         with the primary key could not be found
468             * @throws SystemException if a system exception occurred
469             */
470            @Override
471            public Company fetchCompanyById(long companyId) throws SystemException {
472                    return companyPersistence.fetchByPrimaryKey(companyId);
473            }
474    
475            /**
476             * Returns the company with the virtual host name.
477             *
478             * @param  virtualHostname the virtual host name
479             * @return the company with the virtual host name, <code>null</code> if a
480             *         company with the virtual host could not be found
481             * @throws SystemException if a system exception occurred
482             */
483            @Override
484            public Company fetchCompanyByVirtualHost(String virtualHostname)
485                    throws SystemException {
486    
487                    virtualHostname = virtualHostname.trim().toLowerCase();
488    
489                    VirtualHost virtualHost = virtualHostPersistence.fetchByHostname(
490                            virtualHostname);
491    
492                    if ((virtualHost == null) || (virtualHost.getLayoutSetId() != 0)) {
493                            return null;
494                    }
495    
496                    return companyPersistence.fetchByPrimaryKey(virtualHost.getCompanyId());
497            }
498    
499            /**
500             * Returns all the companies.
501             *
502             * @return the companies
503             * @throws SystemException if a system exception occurred
504             */
505            @Override
506            public List<Company> getCompanies() throws SystemException {
507                    return companyPersistence.findAll();
508            }
509    
510            /**
511             * Returns all the companies used by WSRP.
512             *
513             * @param  system whether the company is the very first company (i.e., the
514             *         super company)
515             * @return the companies used by WSRP
516             * @throws SystemException if a system exception occurred
517             */
518            @Override
519            public List<Company> getCompanies(boolean system) throws SystemException {
520                    return companyPersistence.findBySystem(system);
521            }
522    
523            /**
524             * Returns the number of companies used by WSRP.
525             *
526             * @param  system whether the company is the very first company (i.e., the
527             *         super company)
528             * @return the number of companies used by WSRP
529             * @throws SystemException if a system exception occurred
530             */
531            @Override
532            public int getCompaniesCount(boolean system) throws SystemException {
533                    return companyPersistence.countBySystem(system);
534            }
535    
536            /**
537             * Returns the company with the primary key.
538             *
539             * @param  companyId the primary key of the company
540             * @return the company with the primary key
541             * @throws PortalException if a company with the primary key could not be
542             *         found
543             * @throws SystemException if a system exception occurred
544             */
545            @Override
546            public Company getCompanyById(long companyId)
547                    throws PortalException, SystemException {
548    
549                    return companyPersistence.findByPrimaryKey(companyId);
550            }
551    
552            /**
553             * Returns the company with the logo.
554             *
555             * @param  logoId the ID of the company's logo
556             * @return the company with the logo
557             * @throws PortalException if the company with the logo could not be found
558             * @throws SystemException if a system exception occurred
559             */
560            @Override
561            public Company getCompanyByLogoId(long logoId)
562                    throws PortalException, SystemException {
563    
564                    return companyPersistence.findByLogoId(logoId);
565            }
566    
567            /**
568             * Returns the company with the mail domain.
569             *
570             * @param  mx the company's mail domain
571             * @return the company with the mail domain
572             * @throws PortalException if the company with the mail domain could not be
573             *         found
574             * @throws SystemException if a system exception occurred
575             */
576            @Override
577            public Company getCompanyByMx(String mx)
578                    throws PortalException, SystemException {
579    
580                    return companyPersistence.findByMx(mx);
581            }
582    
583            /**
584             * Returns the company with the virtual host name.
585             *
586             * @param  virtualHostname the company's virtual host name
587             * @return the company with the virtual host name
588             * @throws PortalException if the company with the virtual host name could
589             *         not be found or if the virtual host was not associated with a
590             *         company
591             * @throws SystemException if a system exception occurred
592             */
593            @Override
594            public Company getCompanyByVirtualHost(String virtualHostname)
595                    throws PortalException, SystemException {
596    
597                    try {
598                            virtualHostname = virtualHostname.trim().toLowerCase();
599    
600                            VirtualHost virtualHost = virtualHostPersistence.findByHostname(
601                                    virtualHostname);
602    
603                            if (virtualHost.getLayoutSetId() != 0) {
604                                    throw new CompanyVirtualHostException(
605                                            "Virtual host is associated with layout set " +
606                                                    virtualHost.getLayoutSetId());
607                            }
608    
609                            return companyPersistence.findByPrimaryKey(
610                                    virtualHost.getCompanyId());
611                    }
612                    catch (NoSuchVirtualHostException nsvhe) {
613                            throw new CompanyVirtualHostException(nsvhe);
614                    }
615            }
616    
617            /**
618             * Returns the company with the web domain.
619             *
620             * @param  webId the company's web domain
621             * @return the company with the web domain
622             * @throws PortalException if the company with the web domain could not be
623             *         found
624             * @throws SystemException if a system exception occurred
625             */
626            @Override
627            public Company getCompanyByWebId(String webId)
628                    throws PortalException, SystemException {
629    
630                    return companyPersistence.findByWebId(webId);
631            }
632    
633            /**
634             * Returns the user's company.
635             *
636             * @param  userId the primary key of the user
637             * @return Returns the first company if there is only one company or the
638             *         user's company if there are more than one company; <code>0</code>
639             *         otherwise
640             * @throws Exception if a user with the primary key could not be found
641             */
642            @Override
643            public long getCompanyIdByUserId(long userId) throws Exception {
644                    long[] companyIds = PortalInstances.getCompanyIds();
645    
646                    long companyId = 0;
647    
648                    if (companyIds.length == 1) {
649                            companyId = companyIds[0];
650                    }
651                    else if (companyIds.length > 1) {
652                            try {
653                                    User user = userPersistence.findByPrimaryKey(userId);
654    
655                                    companyId = user.getCompanyId();
656                            }
657                            catch (Exception e) {
658                                    if (_log.isWarnEnabled()) {
659                                            _log.warn(
660                                                    "Unable to get the company id for user " + userId, e);
661                                    }
662                            }
663                    }
664    
665                    return companyId;
666            }
667    
668            /**
669             * Removes the values that match the keys of the company's preferences.
670             *
671             * This method is called by {@link
672             * com.liferay.portlet.portalsettings.action.EditLDAPServerAction} remotely
673             * through {@link com.liferay.portal.service.CompanyService}.
674             *
675             * @param  companyId the primary key of the company
676             * @param  keys the company's preferences keys to be remove
677             * @throws SystemException if a system exception occurred
678             */
679            @Override
680            public void removePreferences(long companyId, String[] keys)
681                    throws SystemException {
682    
683                    PortletPreferences preferences = PrefsPropsUtil.getPreferences(
684                            companyId);
685    
686                    try {
687                            for (String key : keys) {
688                                    preferences.reset(key);
689                            }
690    
691                            preferences.store();
692                    }
693                    catch (Exception e) {
694                            throw new SystemException(e);
695                    }
696            }
697    
698            /**
699             * Returns an ordered range of all assets that match the keywords in the
700             * company.
701             *
702             * The method is called in {@link
703             * com.liferay.portal.search.PortalOpenSearchImpl} which is not longer used
704             * by the Search portlet.
705             *
706             * @param  companyId the primary key of the company
707             * @param  userId the primary key of the user
708             * @param  keywords the keywords (space separated),which may occur in assets
709             *         in the company (optionally <code>null</code>)
710             * @param  start the lower bound of the range of assets to return
711             * @param  end the upper bound of the range of assets to return (not
712             *         inclusive)
713             * @return the matching assets in the company
714             * @throws SystemException if a system exception occurred
715             */
716            @Override
717            public Hits search(
718                            long companyId, long userId, String keywords, int start, int end)
719                    throws SystemException {
720    
721                    return search(companyId, userId, null, 0, null, keywords, start, end);
722            }
723    
724            /**
725             * Returns an ordered range of all assets that match the keywords in the
726             * portlet within the company.
727             *
728             * @param  companyId the primary key of the company
729             * @param  userId the primary key of the user
730             * @param  portletId the primary key of the portlet (optionally
731             *         <code>null</code>)
732             * @param  groupId the primary key of the group (optionally <code>0</code>)
733             * @param  type the mime type of assets to return(optionally
734             *         <code>null</code>)
735             * @param  keywords the keywords (space separated), which may occur in any
736             *         assets in the portlet (optionally <code>null</code>)
737             * @param  start the lower bound of the range of assets to return
738             * @param  end the upper bound of the range of assets to return (not
739             *         inclusive)
740             * @return the matching assets in the portlet within the company
741             * @throws SystemException if a system exception occurred
742             */
743            @Override
744            public Hits search(
745                            long companyId, long userId, String portletId, long groupId,
746                            String type, String keywords, int start, int end)
747                    throws SystemException {
748    
749                    try {
750    
751                            // Search context
752    
753                            SearchContext searchContext = new SearchContext();
754    
755                            searchContext.setCompanyId(companyId);
756                            searchContext.setEnd(end);
757                            searchContext.setEntryClassNames(
758                                    SearchEngineUtil.getEntryClassNames());
759    
760                            if (groupId > 0) {
761                                    searchContext.setGroupIds(new long[] {groupId});
762                            }
763    
764                            searchContext.setKeywords(keywords);
765    
766                            if (Validator.isNotNull(portletId)) {
767                                    searchContext.setPortletIds(new String[] {portletId});
768                            }
769    
770                            searchContext.setStart(start);
771                            searchContext.setUserId(userId);
772    
773                            // Always add facets as late as possible so that the search context
774                            // fields can be considered by the facets
775    
776                            Facet assetEntriesFacet = new AssetEntriesFacet(searchContext);
777    
778                            assetEntriesFacet.setStatic(true);
779    
780                            searchContext.addFacet(assetEntriesFacet);
781    
782                            Facet scopeFacet = new ScopeFacet(searchContext);
783    
784                            scopeFacet.setStatic(true);
785    
786                            searchContext.addFacet(scopeFacet);
787    
788                            // Search
789    
790                            Indexer indexer = FacetedSearcher.getInstance();
791    
792                            return indexer.search(searchContext);
793                    }
794                    catch (Exception e) {
795                            throw new SystemException(e);
796                    }
797            }
798    
799            /**
800             * Updates the company.
801             *
802             * @param  companyId the primary key of the company
803             * @param  virtualHostname the company's virtual host name
804             * @param  mx the company's mail domain
805             * @param  maxUsers the max number of company users (optionally
806             *         <code>0</code>)
807             * @param  active whether the company is active
808             * @return the company with the primary key
809             * @throws PortalException if a company with primary key could not be found
810             *         or if the new information was invalid
811             * @throws SystemException if a system exception occurred
812             */
813            @Override
814            public Company updateCompany(
815                            long companyId, String virtualHostname, String mx, int maxUsers,
816                            boolean active)
817                    throws PortalException, SystemException {
818    
819                    // Company
820    
821                    virtualHostname = virtualHostname.trim().toLowerCase();
822    
823                    if (!active) {
824                            if (companyId == PortalInstances.getDefaultCompanyId()) {
825                                    active = true;
826                            }
827                    }
828    
829                    Company company = companyPersistence.findByPrimaryKey(companyId);
830    
831                    validate(company.getWebId(), virtualHostname, mx);
832    
833                    if (PropsValues.MAIL_MX_UPDATE) {
834                            company.setMx(mx);
835                    }
836    
837                    company.setMaxUsers(maxUsers);
838                    company.setActive(active);
839    
840                    companyPersistence.update(company, false);
841    
842                    // Virtual host
843    
844                    updateVirtualHost(companyId, virtualHostname);
845    
846                    return company;
847            }
848    
849            /**
850             * Update the company with additional account information.
851             *
852             * @param  companyId the primary key of the company
853             * @param  virtualHostname the company's virtual host name
854             * @param  mx the company's mail domain
855             * @param  homeURL the company's home URL (optionally <code>null</code>)
856             * @param  name the company's account name(optionally <code>null</code>)
857             * @param  legalName the company's account legal name (optionally
858             *         <code>null</code>)
859             * @param  legalId the company's account legal ID (optionally
860             *         <code>null</code>)
861             * @param  legalType the company's account legal type (optionally
862             *         <code>null</code>)
863             * @param  sicCode the company's account SIC code (optionally
864             *         <code>null</code>)
865             * @param  tickerSymbol the company's account ticker symbol (optionally
866             *         <code>null</code>)
867             * @param  industry the company's account industry (optionally
868             *         <code>null</code>)
869             * @param  type the company's account type (optionally <code>null</code>)
870             * @param  size the company's account size (optionally <code>null</code>)
871             * @return the company with the primary key
872             * @throws PortalException if a company with the primary key could not be
873             *         found or if the new information was invalid
874             * @throws SystemException if a system exception occurred
875             */
876            @Override
877            public Company updateCompany(
878                            long companyId, String virtualHostname, String mx, String homeURL,
879                            String name, String legalName, String legalId, String legalType,
880                            String sicCode, String tickerSymbol, String industry, String type,
881                            String size)
882                    throws PortalException, SystemException {
883    
884                    // Company
885    
886                    virtualHostname = virtualHostname.trim().toLowerCase();
887    
888                    Company company = companyPersistence.findByPrimaryKey(companyId);
889    
890                    validate(company.getWebId(), virtualHostname, mx);
891                    validate(companyId, name);
892    
893                    if (PropsValues.MAIL_MX_UPDATE) {
894                            company.setMx(mx);
895                    }
896    
897                    company.setHomeURL(homeURL);
898    
899                    companyPersistence.update(company, false);
900    
901                    // Account
902    
903                    updateAccount(
904                            company, name, legalName, legalId, legalType, sicCode, tickerSymbol,
905                            industry, type, size);
906    
907                    // Virtual host
908    
909                    updateVirtualHost(companyId, virtualHostname);
910    
911                    return company;
912            }
913    
914            /**
915             * Update the company's display.
916             *
917             * @param  companyId the primary key of the company
918             * @param  languageId the ID of the company's default user's language
919             * @param  timeZoneId the ID of the company's default user's time zone
920             * @throws PortalException if the company's default user could not be found
921             * @throws SystemException if a system exception occurred
922             */
923            @Override
924            public void updateDisplay(
925                            long companyId, String languageId, String timeZoneId)
926                    throws PortalException, SystemException {
927    
928                    User user = userLocalService.getDefaultUser(companyId);
929    
930                    user.setLanguageId(languageId);
931                    user.setTimeZoneId(timeZoneId);
932    
933                    userPersistence.update(user, false);
934            }
935    
936            /**
937             * Updates the company's logo.
938             *
939             * @param  companyId the primary key of the company
940             * @param  bytes the bytes of the company's logo image
941             * @return the company with the primary key
942             * @throws PortalException if the company's logo ID could not be found or if
943             *         the logo's image was corrupted
944             * @throws SystemException if a system exception occurred
945             */
946            @Override
947            public Company updateLogo(long companyId, byte[] bytes)
948                    throws PortalException, SystemException {
949    
950                    Company company = checkLogo(companyId);
951    
952                    imageLocalService.updateImage(company.getLogoId(), bytes);
953    
954                    return company;
955            }
956    
957            /**
958             * Updates the company's logo.
959             *
960             * @param  companyId the primary key of the company
961             * @param  file the file of the company's logo image
962             * @return the company with the primary key
963             * @throws PortalException the company's logo ID could not be found or if
964             *         the logo's image was corrupted
965             * @throws SystemException if a system exception occurred
966             */
967            @Override
968            public Company updateLogo(long companyId, File file)
969                    throws PortalException, SystemException {
970    
971                    Company company = checkLogo(companyId);
972    
973                    imageLocalService.updateImage(company.getLogoId(), file);
974    
975                    return company;
976            }
977    
978            /**
979             * Update the company's logo.
980             *
981             * @param  companyId the primary key of the company
982             * @param  is the input stream of the company's logo image
983             * @return the company with the primary key
984             * @throws PortalException if the company's logo ID could not be found or if
985             *         the company's logo image was corrupted
986             * @throws SystemException if a system exception occurred
987             */
988            @Override
989            public Company updateLogo(long companyId, InputStream is)
990                    throws PortalException, SystemException {
991    
992                    Company company = checkLogo(companyId);
993    
994                    imageLocalService.updateImage(company.getLogoId(), is);
995    
996                    return company;
997            }
998    
999            /**
1000             * Updates the company's preferences. The company's default properties are
1001             * found in portal.properties.
1002             *
1003             * @param  companyId the primary key of the company
1004             * @param  properties the company's properties. See {@link
1005             *         com.liferay.portal.kernel.util.UnicodeProperties}
1006             * @throws PortalException if the properties contained new locales that were
1007             *         not supported
1008             * @throws SystemException if a system exception occurred
1009             */
1010            @Override
1011            public void updatePreferences(long companyId, UnicodeProperties properties)
1012                    throws PortalException, SystemException {
1013    
1014                    PortletPreferences preferences = PrefsPropsUtil.getPreferences(
1015                            companyId);
1016    
1017                    try {
1018                            String newLocales = properties.getProperty(PropsKeys.LOCALES);
1019    
1020                            if (newLocales != null) {
1021                                    String oldLocales = preferences.getValue(
1022                                            PropsKeys.LOCALES, StringPool.BLANK);
1023    
1024                                    if (!Validator.equals(oldLocales, newLocales)) {
1025                                            validateLocales(newLocales);
1026    
1027                                            LanguageUtil.resetAvailableLocales(companyId);
1028    
1029                                            // Invalidate cache of all layout set prototypes that belong
1030                                            // to this company. See LPS-36403.
1031    
1032                                            Date now = new Date();
1033    
1034                                            for (LayoutSetPrototype layoutSetPrototype :
1035                                                            layoutSetPrototypeLocalService.
1036                                                                    getLayoutSetPrototypes(companyId)) {
1037    
1038                                                    layoutSetPrototype.setModifiedDate(now);
1039    
1040                                                    layoutSetPrototypeLocalService.updateLayoutSetPrototype(
1041                                                            layoutSetPrototype);
1042                                            }
1043                                    }
1044                            }
1045    
1046                            List<String> resetKeys = new ArrayList<String>();
1047    
1048                            for (Map.Entry<String, String> entry : properties.entrySet()) {
1049                                    String key = entry.getKey();
1050                                    String value = entry.getValue();
1051    
1052                                    if (value.equals(Portal.TEMP_OBFUSCATION_VALUE)) {
1053                                            continue;
1054                                    }
1055    
1056                                    String propsUtilValue = PropsUtil.get(key);
1057    
1058                                    if (!value.equals(propsUtilValue)) {
1059                                            preferences.setValue(key, value);
1060                                    }
1061                                    else {
1062                                            String preferencesValue = preferences.getValue(key, null);
1063    
1064                                            if (preferencesValue != null) {
1065                                                    resetKeys.add(key);
1066                                            }
1067                                    }
1068                            }
1069    
1070                            for (String key : resetKeys) {
1071                                    preferences.reset(key);
1072                            }
1073    
1074                            preferences.store();
1075                    }
1076                    catch (LocaleException le) {
1077                            throw le;
1078                    }
1079                    catch (Exception e) {
1080                            throw new SystemException(e);
1081                    }
1082            }
1083    
1084            /**
1085             * Updates the company's security properties.
1086             *
1087             * @param  companyId the primary key of the company
1088             * @param  authType the company's method of authenticating users
1089             * @param  autoLogin whether to allow users to select the "remember me"
1090             *         feature
1091             * @param  sendPassword whether to allow users to ask the company to send
1092             *         their password
1093             * @param  strangers whether to allow strangers to create accounts register
1094             *         themselves in the company
1095             * @param  strangersWithMx whether to allow strangers to create accounts
1096             *         with email addresses that match the company mail suffix
1097             * @param  strangersVerify whether to require strangers who create accounts
1098             *         to be verified via email
1099             * @param  siteLogo whether to allow site administrators to use their own
1100             *         logo instead of the enterprise logo
1101             * @throws SystemException if a system exception occurred
1102             */
1103            @Override
1104            public void updateSecurity(
1105                            long companyId, String authType, boolean autoLogin,
1106                            boolean sendPassword, boolean strangers, boolean strangersWithMx,
1107                            boolean strangersVerify, boolean siteLogo)
1108                    throws SystemException {
1109    
1110                    PortletPreferences preferences = PrefsPropsUtil.getPreferences(
1111                            companyId);
1112    
1113                    try {
1114                            preferences.setValue(
1115                                    PropsKeys.COMPANY_SECURITY_AUTH_TYPE, authType);
1116                            preferences.setValue(
1117                                    PropsKeys.COMPANY_SECURITY_AUTO_LOGIN,
1118                                    String.valueOf(autoLogin));
1119                            preferences.setValue(
1120                                    PropsKeys.COMPANY_SECURITY_SEND_PASSWORD,
1121                                    String.valueOf(sendPassword));
1122                            preferences.setValue(
1123                                    PropsKeys.COMPANY_SECURITY_STRANGERS,
1124                                    String.valueOf(strangers));
1125                            preferences.setValue(
1126                                    PropsKeys.COMPANY_SECURITY_STRANGERS_WITH_MX,
1127                                    String.valueOf(strangersWithMx));
1128                            preferences.setValue(
1129                                    PropsKeys.COMPANY_SECURITY_STRANGERS_VERIFY,
1130                                    String.valueOf(strangersVerify));
1131                            preferences.setValue(
1132                                    PropsKeys.COMPANY_SECURITY_SITE_LOGO, String.valueOf(siteLogo));
1133    
1134                            preferences.store();
1135                    }
1136                    catch (IOException ioe) {
1137                            throw new SystemException(ioe);
1138                    }
1139                    catch (PortletException pe) {
1140                            throw new SystemException(pe);
1141                    }
1142            }
1143    
1144            protected Company checkLogo(long companyId)
1145                    throws PortalException, SystemException {
1146    
1147                    Company company = companyPersistence.findByPrimaryKey(companyId);
1148    
1149                    long logoId = company.getLogoId();
1150    
1151                    if (logoId <= 0) {
1152                            logoId = counterLocalService.increment();
1153    
1154                            company.setLogoId(logoId);
1155    
1156                            company = companyPersistence.update(company, false);
1157                    }
1158    
1159                    return company;
1160            }
1161    
1162            protected void updateAccount(
1163                            Company company, String name, String legalName, String legalId,
1164                            String legalType, String sicCode, String tickerSymbol,
1165                            String industry, String type, String size)
1166                    throws SystemException {
1167    
1168                    Date now = new Date();
1169    
1170                    Account account = accountPersistence.fetchByPrimaryKey(
1171                            company.getAccountId());
1172    
1173                    if (account == null) {
1174                            long accountId = counterLocalService.increment();
1175    
1176                            account = accountPersistence.create(accountId);
1177    
1178                            account.setCompanyId(company.getCompanyId());
1179                            account.setCreateDate(now);
1180                            account.setUserId(0);
1181                            account.setUserName(StringPool.BLANK);
1182    
1183                            company.setAccountId(accountId);
1184    
1185                            companyPersistence.update(company, false);
1186                    }
1187    
1188                    account.setModifiedDate(now);
1189                    account.setName(name);
1190                    account.setLegalName(legalName);
1191                    account.setLegalId(legalId);
1192                    account.setLegalType(legalType);
1193                    account.setSicCode(sicCode);
1194                    account.setTickerSymbol(tickerSymbol);
1195                    account.setIndustry(industry);
1196                    account.setType(type);
1197                    account.setSize(size);
1198    
1199                    accountPersistence.update(account, false);
1200            }
1201    
1202            protected void updateVirtualHost(long companyId, String virtualHostname)
1203                    throws CompanyVirtualHostException, SystemException {
1204    
1205                    if (Validator.isNotNull(virtualHostname)) {
1206                            try {
1207                                    VirtualHost virtualHost = virtualHostPersistence.findByHostname(
1208                                            virtualHostname);
1209    
1210                                    if ((virtualHost.getCompanyId() != companyId) ||
1211                                            (virtualHost.getLayoutSetId() != 0)) {
1212    
1213                                            throw new CompanyVirtualHostException();
1214                                    }
1215                            }
1216                            catch (NoSuchVirtualHostException nsvhe) {
1217                                    virtualHostLocalService.updateVirtualHost(
1218                                            companyId, 0, virtualHostname);
1219                            }
1220                    }
1221                    else {
1222                            try {
1223                                    virtualHostPersistence.removeByC_L(companyId, 0);
1224                            }
1225                            catch (NoSuchVirtualHostException nsvhe) {
1226                            }
1227                    }
1228            }
1229    
1230            protected void validate(long companyId, String name)
1231                    throws PortalException, SystemException {
1232    
1233                    Group group = groupLocalService.fetchGroup(companyId, name);
1234    
1235                    if ((group != null) || Validator.isNull(name)) {
1236                            throw new AccountNameException();
1237                    }
1238            }
1239    
1240            protected void validate(String webId, String virtualHostname, String mx)
1241                    throws PortalException, SystemException {
1242    
1243                    if (Validator.isNull(virtualHostname)) {
1244                            throw new CompanyVirtualHostException();
1245                    }
1246                    else if (virtualHostname.equals(_DEFAULT_VIRTUAL_HOST) &&
1247                                     !webId.equals(PropsValues.COMPANY_DEFAULT_WEB_ID)) {
1248    
1249                            throw new CompanyVirtualHostException();
1250                    }
1251                    else if (!Validator.isDomain(virtualHostname)) {
1252                            throw new CompanyVirtualHostException();
1253                    }
1254                    else {
1255                            try {
1256                                    VirtualHost virtualHost = virtualHostPersistence.findByHostname(
1257                                            virtualHostname);
1258    
1259                                    long companyId = virtualHost.getCompanyId();
1260    
1261                                    Company virtualHostnameCompany =
1262                                            companyPersistence.findByPrimaryKey(companyId);
1263    
1264                                    if (!virtualHostnameCompany.getWebId().equals(webId)) {
1265                                            throw new CompanyVirtualHostException();
1266                                    }
1267                            }
1268                            catch (NoSuchVirtualHostException nsvhe) {
1269                            }
1270                    }
1271    
1272                    if (Validator.isNull(mx)) {
1273                            throw new CompanyMxException();
1274                    }
1275                    else if (!Validator.isDomain(mx)) {
1276                            throw new CompanyMxException();
1277                    }
1278            }
1279    
1280            protected void validateLocales(String locales) throws PortalException {
1281                    String[] localesArray = StringUtil.split(locales, StringPool.COMMA);
1282    
1283                    for (String locale : localesArray) {
1284                            if (!ArrayUtil.contains(PropsValues.LOCALES, locale)) {
1285                                    throw new LocaleException();
1286                            }
1287                    }
1288            }
1289    
1290            private static final String _DEFAULT_VIRTUAL_HOST = "localhost";
1291    
1292            private static Log _log = LogFactoryUtil.getLog(
1293                    CompanyLocalServiceImpl.class);
1294    
1295    }