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    
158                    String jndiName = StringPool.BLANK;
159    
160                    if (Validator.isNotNull(PropsValues.JDBC_DEFAULT_JNDI_NAME)) {
161                            jndiName = PropsValues.JDBC_DEFAULT_JNDI_NAME;
162                    }
163    
164                    _testConnection(driverClassName, url, userName, password, jndiName);
165            }
166    
167            public static void updateLanguage(
168                    HttpServletRequest request, HttpServletResponse response) {
169    
170                    String languageId = ParamUtil.getString(
171                            request, "companyLocale", getDefaultLanguageId());
172    
173                    Locale locale = LocaleUtil.fromLanguageId(languageId);
174    
175                    List<Locale> availableLocales = ListUtil.fromArray(
176                            LanguageUtil.getAvailableLocales());
177    
178                    if (!availableLocales.contains(locale)) {
179                            return;
180                    }
181    
182                    HttpSession session = request.getSession();
183    
184                    session.setAttribute(Globals.LOCALE_KEY, locale);
185                    session.setAttribute(WebKeys.SETUP_WIZARD_DEFAULT_LOCALE, languageId);
186    
187                    LanguageUtil.updateCookie(request, response, locale);
188    
189                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
190                            WebKeys.THEME_DISPLAY);
191    
192                    themeDisplay.setLanguageId(languageId);
193                    themeDisplay.setLocale(locale);
194            }
195    
196            public static void updateSetup(
197                            HttpServletRequest request, HttpServletResponse response)
198                    throws Exception {
199    
200                    UnicodeProperties unicodeProperties = PropertiesParamUtil.getProperties(
201                            request, _PROPERTIES_PREFIX);
202    
203                    unicodeProperties.setProperty(
204                            PropsKeys.LIFERAY_HOME,
205                            SystemProperties.get(PropsKeys.LIFERAY_HOME));
206    
207                    boolean databaseConfigured = _isDatabaseConfigured(unicodeProperties);
208    
209                    _processDatabaseProperties(
210                            request, unicodeProperties, databaseConfigured);
211    
212                    updateLanguage(request, response);
213    
214                    unicodeProperties.put(
215                            PropsKeys.SETUP_WIZARD_ENABLED, String.valueOf(false));
216    
217                    PropsUtil.addProperties(unicodeProperties);
218    
219                    if (!databaseConfigured) {
220                            _reloadServletContext(request, unicodeProperties);
221                    }
222    
223                    _updateCompany(request);
224                    _updateAdminUser(request, unicodeProperties);
225    
226                    _initPlugins();
227    
228                    if (ParamUtil.getBoolean(request, "addSampleData")) {
229                            SetupWizardSampleDataUtil.addSampleData(
230                                    PortalInstances.getDefaultCompanyId());
231                    }
232    
233                    HttpSession session = request.getSession();
234    
235                    session.setAttribute(
236                            WebKeys.SETUP_WIZARD_PROPERTIES, unicodeProperties);
237                    session.setAttribute(
238                            WebKeys.SETUP_WIZARD_PROPERTIES_FILE_CREATED,
239                            _writePropertiesFile(unicodeProperties));
240            }
241    
242            private static String _getParameter(
243                    HttpServletRequest request, String name, String defaultValue) {
244    
245                    name = _PROPERTIES_PREFIX.concat(name).concat(StringPool.DOUBLE_DASH);
246    
247                    return ParamUtil.getString(request, name, defaultValue);
248            }
249    
250            /**
251             * @see {@link com.liferay.portal.servlet.MainServlet#initPlugins}
252             */
253            private static void _initPlugins() {
254                    HotDeployUtil.setCapturePrematureEvents(false);
255    
256                    PortalLifecycleUtil.flushInits();
257            }
258    
259            private static boolean _isDatabaseConfigured(
260                    UnicodeProperties unicodeProperties) {
261    
262                    String defaultDriverClassName = unicodeProperties.get(
263                            PropsKeys.JDBC_DEFAULT_DRIVER_CLASS_NAME);
264                    String defaultPassword = unicodeProperties.get(
265                            PropsKeys.JDBC_DEFAULT_PASSWORD);
266                    String defaultURL = unicodeProperties.get(PropsKeys.JDBC_DEFAULT_URL);
267                    String defaultUsername = unicodeProperties.get(
268                            PropsKeys.JDBC_DEFAULT_USERNAME);
269    
270                    if (PropsValues.JDBC_DEFAULT_DRIVER_CLASS_NAME.equals(
271                                    defaultDriverClassName) &&
272                            PropsValues.JDBC_DEFAULT_PASSWORD.equals(defaultPassword) &&
273                            PropsValues.JDBC_DEFAULT_URL.equals(defaultURL) &&
274                            PropsValues.JDBC_DEFAULT_USERNAME.equals(defaultUsername) ) {
275    
276                            return true;
277                    }
278    
279                    return false;
280            }
281    
282            private static void _processDatabaseProperties(
283                            HttpServletRequest request, UnicodeProperties unicodeProperties,
284                            boolean databaseConfigured)
285                    throws Exception {
286    
287                    boolean defaultDatabase = ParamUtil.getBoolean(
288                            request, "defaultDatabase", true);
289    
290                    if (defaultDatabase || databaseConfigured) {
291                            unicodeProperties.remove(PropsKeys.JDBC_DEFAULT_URL);
292                            unicodeProperties.remove(PropsKeys.JDBC_DEFAULT_DRIVER_CLASS_NAME);
293                            unicodeProperties.remove(PropsKeys.JDBC_DEFAULT_USERNAME);
294                            unicodeProperties.remove(PropsKeys.JDBC_DEFAULT_PASSWORD);
295                    }
296            }
297    
298            private static void _reconfigurePersistenceBeans() throws Exception {
299                    @SuppressWarnings("rawtypes")
300                    Map<String, BasePersistenceImpl> beanPersistenceImpls =
301                            PortalBeanLocatorUtil.locate(BasePersistenceImpl.class);
302    
303                    SessionFactory sessionFactory =
304                            (SessionFactory)PortalBeanLocatorUtil.locate(
305                                    "liferaySessionFactory");
306    
307                    for (String name : beanPersistenceImpls.keySet()) {
308                            BasePersistenceImpl<?> beanPersistenceImpl =
309                                    beanPersistenceImpls.get(name);
310    
311                            beanPersistenceImpl.setSessionFactory(sessionFactory);
312                    }
313            }
314    
315            private static void _reloadServletContext(
316                            HttpServletRequest request, UnicodeProperties unicodeProperties)
317                    throws Exception {
318    
319                    // Data sources
320    
321                    Properties jdbcProperties = new Properties();
322    
323                    jdbcProperties.putAll(unicodeProperties);
324    
325                    reloadDataSources(jdbcProperties);
326    
327                    // Quartz
328    
329                    QuartzLocalServiceUtil.checkQuartzTables();
330    
331                    // Startup
332    
333                    StartupAction startupAction = new StartupAction();
334    
335                    startupAction.run(null);
336    
337                    // Servlet context
338    
339                    HttpSession session = request.getSession();
340    
341                    PortalInstances.reload(session.getServletContext());
342            }
343    
344            private static void _testConnection(
345                            String driverClassName, String url, String userName,
346                            String password, String jndiName)
347                    throws Exception {
348    
349                    if (Validator.isNull(jndiName)) {
350                            Class.forName(driverClassName);
351                    }
352    
353                    DataSource dataSource = null;
354                    Connection connection = null;
355    
356                    try {
357                            dataSource = DataSourceFactoryUtil.initDataSource(
358                                    driverClassName, url, userName, password, jndiName);
359    
360                            connection = dataSource.getConnection();
361                    }
362                    finally {
363                            DataAccess.cleanUp(connection);
364                            DataSourceFactoryUtil.destroyDataSource(dataSource);
365                    }
366            }
367    
368            private static void _updateAdminUser(
369                            HttpServletRequest request, UnicodeProperties unicodeProperties)
370                    throws Exception {
371    
372                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
373                            WebKeys.THEME_DISPLAY);
374    
375                    Company company = CompanyLocalServiceUtil.getCompanyById(
376                            themeDisplay.getCompanyId());
377    
378                    String emailAddress = ParamUtil.getString(
379                            request, "adminEmailAddress",
380                            PropsValues.DEFAULT_ADMIN_EMAIL_ADDRESS_PREFIX + StringPool.AT +
381                                    company.getMx());
382    
383                    PropsValues.ADMIN_EMAIL_FROM_ADDRESS = emailAddress;
384    
385                    unicodeProperties.put(PropsKeys.ADMIN_EMAIL_FROM_ADDRESS, emailAddress);
386    
387                    ScreenNameGenerator screenNameGenerator =
388                            ScreenNameGeneratorFactory.getInstance();
389    
390                    String screenName = GetterUtil.getString(
391                            PropsValues.DEFAULT_ADMIN_EMAIL_ADDRESS_PREFIX, "test");
392    
393                    try {
394                            screenName = screenNameGenerator.generate(0, 0, emailAddress);
395                    }
396                    catch (Exception e) {
397                    }
398    
399                    String firstName = ParamUtil.getString(
400                            request, "adminFirstName", PropsValues.DEFAULT_ADMIN_FIRST_NAME);
401                    String lastName = ParamUtil.getString(
402                            request, "adminLastName", PropsValues.DEFAULT_ADMIN_LAST_NAME);
403    
404                    FullNameGenerator fullNameGenerator =
405                            FullNameGeneratorFactory.getInstance();
406    
407                    String fullName = fullNameGenerator.getFullName(
408                            firstName, null, lastName);
409    
410                    PropsValues.ADMIN_EMAIL_FROM_NAME = fullName;
411    
412                    unicodeProperties.put(PropsKeys.ADMIN_EMAIL_FROM_NAME, fullName);
413    
414                    User user = UserLocalServiceUtil.fetchUserByEmailAddress(
415                            themeDisplay.getCompanyId(), emailAddress);
416    
417                    if (user != null) {
418                            String greeting = LanguageUtil.format(
419                                    themeDisplay.getLocale(), "welcome-x",
420                                    StringPool.SPACE + fullName, false);
421    
422                            Contact contact = user.getContact();
423    
424                            Calendar birthdayCal = CalendarFactoryUtil.getCalendar();
425    
426                            birthdayCal.setTime(contact.getBirthday());
427    
428                            int birthdayMonth = birthdayCal.get(Calendar.MONTH);
429                            int birthdayDay = birthdayCal.get(Calendar.DAY_OF_MONTH);
430                            int birthdayYear = birthdayCal.get(Calendar.YEAR);
431    
432                            user = UserLocalServiceUtil.updateUser(
433                                    user.getUserId(), StringPool.BLANK, StringPool.BLANK,
434                                    StringPool.BLANK, false, user.getReminderQueryQuestion(),
435                                    user.getReminderQueryAnswer(), screenName, emailAddress,
436                                    user.getFacebookId(), user.getOpenId(),
437                                    themeDisplay.getLanguageId(), user.getTimeZoneId(), greeting,
438                                    user.getComments(), firstName, user.getMiddleName(), lastName,
439                                    contact.getPrefixId(), contact.getSuffixId(), contact.isMale(),
440                                    birthdayMonth, birthdayDay, birthdayYear, contact.getSmsSn(),
441                                    contact.getAimSn(), contact.getFacebookSn(), contact.getIcqSn(),
442                                    contact.getJabberSn(), contact.getMsnSn(),
443                                    contact.getMySpaceSn(), contact.getSkypeSn(),
444                                    contact.getTwitterSn(), contact.getYmSn(),
445                                    contact.getJobTitle(), null, null, null, null, null,
446                                    new ServiceContext());
447                    }
448                    else {
449                            UserLocalServiceUtil.addDefaultAdminUser(
450                                    themeDisplay.getCompanyId(), screenName, emailAddress,
451                                    themeDisplay.getLocale(), firstName, StringPool.BLANK,
452                                    lastName);
453    
454                            user = UserLocalServiceUtil.getUserByEmailAddress(
455                                    themeDisplay.getCompanyId(), emailAddress);
456    
457                            String defaultAdminEmailAddress =
458                                    PropsValues.DEFAULT_ADMIN_EMAIL_ADDRESS_PREFIX + "@" +
459                                            PropsValues.COMPANY_DEFAULT_WEB_ID;
460    
461                            if (!emailAddress.equals(defaultAdminEmailAddress)) {
462                                    User testUser = UserLocalServiceUtil.fetchUserByEmailAddress(
463                                            themeDisplay.getCompanyId(), defaultAdminEmailAddress);
464    
465                                    if (testUser != null) {
466                                            UserLocalServiceUtil.updateStatus(
467                                                    testUser.getUserId(),
468                                                    WorkflowConstants.STATUS_INACTIVE);
469                                    }
470                            }
471                    }
472    
473                    user = UserLocalServiceUtil.updatePasswordReset(user.getUserId(), true);
474    
475                    HttpSession session = request.getSession();
476    
477                    session.setAttribute(WebKeys.EMAIL_ADDRESS, emailAddress);
478                    session.setAttribute(WebKeys.SETUP_WIZARD_PASSWORD_UPDATED, true);
479                    session.setAttribute(WebKeys.USER_ID, user.getUserId());
480            }
481    
482            private static void _updateCompany(HttpServletRequest request)
483                    throws Exception {
484    
485                    Company company = CompanyLocalServiceUtil.getCompanyById(
486                            PortalInstances.getDefaultCompanyId());
487    
488                    Account account = company.getAccount();
489    
490                    String currentName = account.getName();
491    
492                    String newName = ParamUtil.getString(
493                            request, "companyName", PropsValues.COMPANY_DEFAULT_NAME);
494    
495                    if (!currentName.equals(newName)) {
496                            account.setName(newName);
497    
498                            AccountLocalServiceUtil.updateAccount(account);
499                    }
500    
501                    String languageId = ParamUtil.getString(
502                            request, "companyLocale", getDefaultLanguageId());
503    
504                    User defaultUser = company.getDefaultUser();
505    
506                    defaultUser.setLanguageId(languageId);
507    
508                    UserLocalServiceUtil.updateUser(defaultUser);
509    
510                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
511                            WebKeys.THEME_DISPLAY);
512    
513                    themeDisplay.setCompany(company);
514            }
515    
516            private static boolean _writePropertiesFile(
517                    UnicodeProperties unicodeProperties) {
518    
519                    try {
520                            FileUtil.write(
521                                    PropsValues.LIFERAY_HOME, PROPERTIES_FILE_NAME,
522                                    unicodeProperties.toString());
523    
524                            if (FileUtil.exists(
525                                            PropsValues.LIFERAY_HOME + StringPool.SLASH +
526                                                    PROPERTIES_FILE_NAME)) {
527    
528                                    return true;
529                            }
530                    }
531                    catch (IOException ioe) {
532                            _log.error(ioe, ioe);
533                    }
534    
535                    return false;
536            }
537    
538            private static final String _PROPERTIES_PREFIX = "properties--";
539    
540            private static Log _log = LogFactoryUtil.getLog(SetupWizardUtil.class);
541    
542            private static boolean _setupFinished = false;
543    
544    }