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.setup;
016    
017    import com.liferay.portal.dao.jdbc.util.DataSourceSwapper;
018    import com.liferay.portal.events.StartupAction;
019    import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
020    import com.liferay.portal.kernel.cache.CacheRegistryUtil;
021    import com.liferay.portal.kernel.cache.MultiVMPoolUtil;
022    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
023    import com.liferay.portal.kernel.dao.jdbc.DataSourceFactoryUtil;
024    import com.liferay.portal.kernel.dao.orm.SessionFactory;
025    import com.liferay.portal.kernel.deploy.hot.HotDeployUtil;
026    import com.liferay.portal.kernel.language.LanguageUtil;
027    import com.liferay.portal.kernel.log.Log;
028    import com.liferay.portal.kernel.log.LogFactoryUtil;
029    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
030    import com.liferay.portal.kernel.util.CentralizedThreadLocal;
031    import com.liferay.portal.kernel.util.FileUtil;
032    import com.liferay.portal.kernel.util.GetterUtil;
033    import com.liferay.portal.kernel.util.ListUtil;
034    import com.liferay.portal.kernel.util.LocaleUtil;
035    import com.liferay.portal.kernel.util.ParamUtil;
036    import com.liferay.portal.kernel.util.PortalLifecycleUtil;
037    import com.liferay.portal.kernel.util.PropertiesParamUtil;
038    import com.liferay.portal.kernel.util.PropertiesUtil;
039    import com.liferay.portal.kernel.util.PropsKeys;
040    import com.liferay.portal.kernel.util.StringPool;
041    import com.liferay.portal.kernel.util.SystemProperties;
042    import com.liferay.portal.kernel.util.UnicodeProperties;
043    import com.liferay.portal.kernel.util.Validator;
044    import com.liferay.portal.kernel.webcache.WebCachePoolUtil;
045    import com.liferay.portal.kernel.workflow.WorkflowConstants;
046    import com.liferay.portal.model.Account;
047    import com.liferay.portal.model.Company;
048    import com.liferay.portal.model.Contact;
049    import com.liferay.portal.model.User;
050    import com.liferay.portal.security.auth.FullNameGenerator;
051    import com.liferay.portal.security.auth.FullNameGeneratorFactory;
052    import com.liferay.portal.security.auth.ScreenNameGenerator;
053    import com.liferay.portal.security.auth.ScreenNameGeneratorFactory;
054    import com.liferay.portal.service.AccountLocalServiceUtil;
055    import com.liferay.portal.service.CompanyLocalServiceUtil;
056    import com.liferay.portal.service.QuartzLocalServiceUtil;
057    import com.liferay.portal.service.ServiceContext;
058    import com.liferay.portal.service.UserLocalServiceUtil;
059    import com.liferay.portal.service.persistence.impl.BasePersistenceImpl;
060    import com.liferay.portal.theme.ThemeDisplay;
061    import com.liferay.portal.util.PortalInstances;
062    import com.liferay.portal.util.PropsUtil;
063    import com.liferay.portal.util.PropsValues;
064    import com.liferay.portal.util.WebKeys;
065    
066    import java.io.IOException;
067    
068    import java.sql.Connection;
069    
070    import java.util.Calendar;
071    import java.util.List;
072    import java.util.Locale;
073    import java.util.Map;
074    import java.util.Properties;
075    
076    import javax.servlet.http.HttpServletRequest;
077    import javax.servlet.http.HttpServletResponse;
078    import javax.servlet.http.HttpSession;
079    
080    import javax.sql.DataSource;
081    
082    import org.apache.struts.Globals;
083    
084    /**
085     * @author Manuel de la Pe??a
086     * @author Julio Camarero
087     * @author Brian Wing Shun Chan
088     * @author Miguel Pastor
089     */
090    public class SetupWizardUtil {
091    
092            public static final String PROPERTIES_FILE_NAME =
093                    "portal-setup-wizard.properties";
094    
095            public static String getDefaultLanguageId() {
096                    Locale defaultLocale = LocaleUtil.getDefault();
097    
098                    return LocaleUtil.toLanguageId(defaultLocale);
099            }
100    
101            public static boolean isDefaultDatabase(HttpServletRequest request) {
102                    boolean hsqldb = ParamUtil.getBoolean(
103                            request, "defaultDatabase",
104                            PropsValues.JDBC_DEFAULT_URL.contains("hsqldb"));
105    
106                    boolean jndi = Validator.isNotNull(PropsValues.JDBC_DEFAULT_JNDI_NAME);
107    
108                    return hsqldb && !jndi;
109            }
110    
111            public static boolean isSetupFinished() {
112                    if (PropsValues.SETUP_WIZARD_ENABLED) {
113                            return _setupFinished;
114                    }
115    
116                    return true;
117            }
118    
119            public static void reloadDataSources(Properties jdbcProperties)
120                    throws Exception {
121    
122                    // Data sources
123    
124                    jdbcProperties = PropertiesUtil.getProperties(
125                            jdbcProperties,"jdbc.default.",true);
126    
127                    DataSourceSwapper.swapCounterDataSource(jdbcProperties);
128                    DataSourceSwapper.swapLiferayDataSource(jdbcProperties);
129    
130                    // Caches
131    
132                    CacheRegistryUtil.clear();
133                    MultiVMPoolUtil.clear();
134                    WebCachePoolUtil.clear();
135                    CentralizedThreadLocal.clearShortLivedThreadLocals();
136    
137                    // Persistence beans
138    
139                    _reconfigurePersistenceBeans();
140            }
141    
142            public static void setSetupFinished(boolean setupFinished) {
143                    _setupFinished = setupFinished;
144            }
145    
146            public static void testDatabase(HttpServletRequest request)
147                    throws Exception {
148    
149                    String driverClassName = _getParameter(
150                            request, PropsKeys.JDBC_DEFAULT_DRIVER_CLASS_NAME,
151                            PropsValues.JDBC_DEFAULT_DRIVER_CLASS_NAME);
152                    String url = _getParameter(request, PropsKeys.JDBC_DEFAULT_URL, null);
153                    String userName = _getParameter(
154                            request, PropsKeys.JDBC_DEFAULT_USERNAME, null);
155                    String password = _getParameter(
156                            request, PropsKeys.JDBC_DEFAULT_PASSWORD, null);
157                    String jndiName = StringPool.BLANK;
158    
159                    _testConnection(driverClassName, url, userName, password, jndiName);
160            }
161    
162            public static void updateLanguage(
163                    HttpServletRequest request, HttpServletResponse response) {
164    
165                    String languageId = ParamUtil.getString(
166                            request, "companyLocale", getDefaultLanguageId());
167    
168                    Locale locale = LocaleUtil.fromLanguageId(languageId);
169    
170                    List<Locale> availableLocales = ListUtil.fromArray(
171                            LanguageUtil.getAvailableLocales());
172    
173                    if (!availableLocales.contains(locale)) {
174                            return;
175                    }
176    
177                    HttpSession session = request.getSession();
178    
179                    session.setAttribute(Globals.LOCALE_KEY, locale);
180                    session.setAttribute(WebKeys.SETUP_WIZARD_DEFAULT_LOCALE, languageId);
181    
182                    LanguageUtil.updateCookie(request, response, locale);
183    
184                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
185                            WebKeys.THEME_DISPLAY);
186    
187                    themeDisplay.setLanguageId(languageId);
188                    themeDisplay.setLocale(locale);
189            }
190    
191            public static void updateSetup(
192                            HttpServletRequest request, HttpServletResponse response)
193                    throws Exception {
194    
195                    UnicodeProperties unicodeProperties = PropertiesParamUtil.getProperties(
196                            request, _PROPERTIES_PREFIX);
197    
198                    unicodeProperties.setProperty(
199                            PropsKeys.LIFERAY_HOME,
200                            SystemProperties.get(PropsKeys.LIFERAY_HOME));
201    
202                    boolean databaseConfigured = _isDatabaseConfigured(unicodeProperties);
203    
204                    _processDatabaseProperties(
205                            request, unicodeProperties, databaseConfigured);
206    
207                    updateLanguage(request, response);
208    
209                    unicodeProperties.put(
210                            PropsKeys.SETUP_WIZARD_ENABLED, String.valueOf(false));
211    
212                    PropsUtil.addProperties(unicodeProperties);
213    
214                    if (!databaseConfigured) {
215                            _reloadServletContext(request, unicodeProperties);
216                    }
217    
218                    _updateCompany(request);
219                    _updateAdminUser(request, unicodeProperties);
220    
221                    _initPlugins();
222    
223                    boolean propertiesFileCreated = _writePropertiesFile(unicodeProperties);
224    
225                    HttpSession session = request.getSession();
226    
227                    session.setAttribute(
228                            WebKeys.SETUP_WIZARD_PROPERTIES, unicodeProperties);
229                    session.setAttribute(
230                            WebKeys.SETUP_WIZARD_PROPERTIES_FILE_CREATED,
231                            propertiesFileCreated);
232            }
233    
234            private static String _getParameter(
235                    HttpServletRequest request, String name, String defaultValue) {
236    
237                    name = _PROPERTIES_PREFIX.concat(name).concat(StringPool.DOUBLE_DASH);
238    
239                    return ParamUtil.getString(request, name, defaultValue);
240            }
241    
242            /**
243             * @see {@link com.liferay.portal.servlet.MainServlet#initPlugins}
244             */
245            private static void _initPlugins() {
246                    HotDeployUtil.setCapturePrematureEvents(false);
247    
248                    PortalLifecycleUtil.flushInits();
249            }
250    
251            private static boolean _isDatabaseConfigured(
252                    UnicodeProperties unicodeProperties) {
253    
254                    String defaultDriverClassName = unicodeProperties.get(
255                            PropsKeys.JDBC_DEFAULT_DRIVER_CLASS_NAME);
256                    String defaultPassword = unicodeProperties.get(
257                            PropsKeys.JDBC_DEFAULT_PASSWORD);
258                    String defaultURL = unicodeProperties.get(PropsKeys.JDBC_DEFAULT_URL);
259                    String defaultUsername = unicodeProperties.get(
260                            PropsKeys.JDBC_DEFAULT_USERNAME);
261    
262                    if (PropsValues.JDBC_DEFAULT_DRIVER_CLASS_NAME.equals(
263                                    defaultDriverClassName) &&
264                            PropsValues.JDBC_DEFAULT_PASSWORD.equals(defaultPassword) &&
265                            PropsValues.JDBC_DEFAULT_URL.equals(defaultURL) &&
266                            PropsValues.JDBC_DEFAULT_USERNAME.equals(defaultUsername) ) {
267    
268                            return true;
269                    }
270    
271                    return false;
272            }
273    
274            private static void _processDatabaseProperties(
275                            HttpServletRequest request, UnicodeProperties unicodeProperties,
276                            boolean databaseConfigured)
277                    throws Exception {
278    
279                    boolean defaultDatabase = ParamUtil.getBoolean(
280                            request, "defaultDatabase", true);
281    
282                    if (defaultDatabase || databaseConfigured) {
283                            unicodeProperties.remove(PropsKeys.JDBC_DEFAULT_URL);
284                            unicodeProperties.remove(PropsKeys.JDBC_DEFAULT_DRIVER_CLASS_NAME);
285                            unicodeProperties.remove(PropsKeys.JDBC_DEFAULT_USERNAME);
286                            unicodeProperties.remove(PropsKeys.JDBC_DEFAULT_PASSWORD);
287                    }
288            }
289    
290            private static void _reconfigurePersistenceBeans() throws Exception {
291                    @SuppressWarnings("rawtypes")
292                    Map<String, BasePersistenceImpl> beanPersistenceImpls =
293                            PortalBeanLocatorUtil.locate(BasePersistenceImpl.class);
294    
295                    SessionFactory sessionFactory =
296                            (SessionFactory)PortalBeanLocatorUtil.locate(
297                                    "liferaySessionFactory");
298    
299                    for (String name : beanPersistenceImpls.keySet()) {
300                            BasePersistenceImpl<?> beanPersistenceImpl =
301                                    beanPersistenceImpls.get(name);
302    
303                            beanPersistenceImpl.setSessionFactory(sessionFactory);
304                    }
305            }
306    
307            private static void _reloadServletContext(
308                            HttpServletRequest request, UnicodeProperties unicodeProperties)
309                    throws Exception {
310    
311                    // Data sources
312    
313                    Properties jdbcProperties = new Properties();
314    
315                    jdbcProperties.putAll(unicodeProperties);
316    
317                    reloadDataSources(jdbcProperties);
318    
319                    // Quartz
320    
321                    QuartzLocalServiceUtil.checkQuartzTables();
322    
323                    // Startup
324    
325                    StartupAction startupAction = new StartupAction();
326    
327                    startupAction.run(null);
328    
329                    // Servlet context
330    
331                    HttpSession session = request.getSession();
332    
333                    PortalInstances.reload(session.getServletContext());
334            }
335    
336            private static void _testConnection(
337                            String driverClassName, String url, String userName,
338                            String password, String jndiName)
339                    throws Exception {
340    
341                    Class.forName(driverClassName);
342    
343                    DataSource dataSource = null;
344                    Connection connection = null;
345    
346                    try {
347                            dataSource = DataSourceFactoryUtil.initDataSource(
348                                    driverClassName, url, userName, password, jndiName);
349    
350                            connection = dataSource.getConnection();
351                    }
352                    finally {
353                            DataAccess.cleanUp(connection);
354                            DataSourceFactoryUtil.destroyDataSource(dataSource);
355                    }
356            }
357    
358            private static void _updateAdminUser(
359                            HttpServletRequest request, UnicodeProperties unicodeProperties)
360                    throws Exception {
361    
362                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
363                            WebKeys.THEME_DISPLAY);
364    
365                    Company company = CompanyLocalServiceUtil.getCompanyById(
366                            themeDisplay.getCompanyId());
367    
368                    String emailAddress = ParamUtil.getString(
369                            request, "adminEmailAddress",
370                            PropsValues.DEFAULT_ADMIN_EMAIL_ADDRESS_PREFIX + StringPool.AT +
371                                    company.getMx());
372    
373                    PropsValues.ADMIN_EMAIL_FROM_ADDRESS = emailAddress;
374    
375                    unicodeProperties.put(PropsKeys.ADMIN_EMAIL_FROM_ADDRESS, emailAddress);
376    
377                    ScreenNameGenerator screenNameGenerator =
378                            ScreenNameGeneratorFactory.getInstance();
379    
380                    String screenName = GetterUtil.getString(
381                            PropsValues.DEFAULT_ADMIN_EMAIL_ADDRESS_PREFIX, "test");
382    
383                    try {
384                            screenName = screenNameGenerator.generate(0, 0, emailAddress);
385                    }
386                    catch (Exception e) {
387                    }
388    
389                    String firstName = ParamUtil.getString(
390                            request, "adminFirstName", PropsValues.DEFAULT_ADMIN_FIRST_NAME);
391                    String lastName = ParamUtil.getString(
392                            request, "adminLastName", PropsValues.DEFAULT_ADMIN_LAST_NAME);
393    
394                    FullNameGenerator fullNameGenerator =
395                            FullNameGeneratorFactory.getInstance();
396    
397                    String fullName = fullNameGenerator.getFullName(
398                            firstName, null, lastName);
399    
400                    PropsValues.ADMIN_EMAIL_FROM_NAME = fullName;
401    
402                    unicodeProperties.put(PropsKeys.ADMIN_EMAIL_FROM_NAME, fullName);
403    
404                    User user = UserLocalServiceUtil.fetchUserByEmailAddress(
405                            themeDisplay.getCompanyId(), emailAddress);
406    
407                    if (user != null) {
408                            String greeting = LanguageUtil.format(
409                                    themeDisplay.getLocale(), "welcome-x",
410                                    StringPool.SPACE + fullName, false);
411    
412                            Contact contact = user.getContact();
413    
414                            Calendar birthdayCal = CalendarFactoryUtil.getCalendar();
415    
416                            birthdayCal.setTime(contact.getBirthday());
417    
418                            int birthdayMonth = birthdayCal.get(Calendar.MONTH);
419                            int birthdayDay = birthdayCal.get(Calendar.DAY_OF_MONTH);
420                            int birthdayYear = birthdayCal.get(Calendar.YEAR);
421    
422                            user = UserLocalServiceUtil.updateUser(
423                                    user.getUserId(), StringPool.BLANK, StringPool.BLANK,
424                                    StringPool.BLANK, false, user.getReminderQueryQuestion(),
425                                    user.getReminderQueryAnswer(), screenName, emailAddress,
426                                    user.getFacebookId(), user.getOpenId(),
427                                    themeDisplay.getLanguageId(), user.getTimeZoneId(), greeting,
428                                    user.getComments(), firstName, user.getMiddleName(), lastName,
429                                    contact.getPrefixId(), contact.getSuffixId(), contact.isMale(),
430                                    birthdayMonth, birthdayDay, birthdayYear, contact.getSmsSn(),
431                                    contact.getAimSn(), contact.getFacebookSn(), contact.getIcqSn(),
432                                    contact.getJabberSn(), contact.getMsnSn(),
433                                    contact.getMySpaceSn(), contact.getSkypeSn(),
434                                    contact.getTwitterSn(), contact.getYmSn(),
435                                    contact.getJobTitle(), null, null, null, null, null,
436                                    new ServiceContext());
437                    }
438                    else {
439                            UserLocalServiceUtil.addDefaultAdminUser(
440                                    themeDisplay.getCompanyId(), screenName, emailAddress,
441                                    themeDisplay.getLocale(), firstName, StringPool.BLANK,
442                                    lastName);
443    
444                            user = UserLocalServiceUtil.getUserByEmailAddress(
445                                    themeDisplay.getCompanyId(), emailAddress);
446    
447                            String defaultAdminEmailAddress =
448                                    PropsValues.DEFAULT_ADMIN_EMAIL_ADDRESS_PREFIX + "@" +
449                                            PropsValues.COMPANY_DEFAULT_WEB_ID;
450    
451                            if (!emailAddress.equals(defaultAdminEmailAddress)) {
452                                    User testUser = UserLocalServiceUtil.fetchUserByEmailAddress(
453                                            themeDisplay.getCompanyId(), defaultAdminEmailAddress);
454    
455                                    if (testUser != null) {
456                                            UserLocalServiceUtil.updateStatus(
457                                                    testUser.getUserId(),
458                                                    WorkflowConstants.STATUS_INACTIVE);
459                                    }
460                            }
461                    }
462    
463                    user = UserLocalServiceUtil.updatePasswordReset(user.getUserId(), true);
464    
465                    HttpSession session = request.getSession();
466    
467                    session.setAttribute(WebKeys.EMAIL_ADDRESS, emailAddress);
468                    session.setAttribute(WebKeys.SETUP_WIZARD_PASSWORD_UPDATED, true);
469                    session.setAttribute(WebKeys.USER_ID, user.getUserId());
470            }
471    
472            private static void _updateCompany(HttpServletRequest request)
473                    throws Exception {
474    
475                    Company company = CompanyLocalServiceUtil.getCompanyById(
476                            PortalInstances.getDefaultCompanyId());
477    
478                    Account account = company.getAccount();
479    
480                    String currentName = account.getName();
481    
482                    String newName = ParamUtil.getString(
483                            request, "companyName", PropsValues.COMPANY_DEFAULT_NAME);
484    
485                    if (!currentName.equals(newName)) {
486                            account.setName(newName);
487    
488                            AccountLocalServiceUtil.updateAccount(account);
489                    }
490    
491                    String languageId = ParamUtil.getString(
492                            request, "companyLocale", getDefaultLanguageId());
493    
494                    User defaultUser = company.getDefaultUser();
495    
496                    defaultUser.setLanguageId(languageId);
497    
498                    UserLocalServiceUtil.updateUser(defaultUser);
499    
500                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
501                            WebKeys.THEME_DISPLAY);
502    
503                    themeDisplay.setCompany(company);
504            }
505    
506            private static boolean _writePropertiesFile(
507                    UnicodeProperties unicodeProperties) {
508    
509                    try {
510                            FileUtil.write(
511                                    PropsValues.LIFERAY_HOME, PROPERTIES_FILE_NAME,
512                                    unicodeProperties.toString());
513    
514                            if (FileUtil.exists(
515                                            PropsValues.LIFERAY_HOME + StringPool.SLASH +
516                                                    PROPERTIES_FILE_NAME)) {
517    
518                                    return true;
519                            }
520                    }
521                    catch (IOException ioe) {
522                            _log.error(ioe, ioe);
523                    }
524    
525                    return false;
526            }
527    
528            private static final String _PROPERTIES_PREFIX = "properties--";
529    
530            private static Log _log = LogFactoryUtil.getLog(SetupWizardUtil.class);
531    
532            private static boolean _setupFinished = false;
533    
534    }