001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.service.impl;
016    
017    import com.liferay.portal.NoSuchReleaseException;
018    import com.liferay.portal.kernel.dao.db.DB;
019    import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
020    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
021    import com.liferay.portal.kernel.exception.PortalException;
022    import com.liferay.portal.kernel.exception.SystemException;
023    import com.liferay.portal.kernel.log.Log;
024    import com.liferay.portal.kernel.log.LogFactoryUtil;
025    import com.liferay.portal.kernel.upgrade.UpgradeException;
026    import com.liferay.portal.kernel.upgrade.UpgradeProcess;
027    import com.liferay.portal.kernel.upgrade.util.UpgradeProcessUtil;
028    import com.liferay.portal.kernel.util.GetterUtil;
029    import com.liferay.portal.kernel.util.PropsKeys;
030    import com.liferay.portal.kernel.util.StringUtil;
031    import com.liferay.portal.kernel.util.Validator;
032    import com.liferay.portal.model.Release;
033    import com.liferay.portal.model.ReleaseConstants;
034    import com.liferay.portal.service.base.ReleaseLocalServiceBaseImpl;
035    import com.liferay.portal.util.PropsUtil;
036    import com.liferay.portal.util.PropsValues;
037    
038    import java.sql.Connection;
039    import java.sql.PreparedStatement;
040    import java.sql.ResultSet;
041    
042    import java.util.Date;
043    import java.util.List;
044    import java.util.Properties;
045    
046    /**
047     * @author Brian Wing Shun Chan
048     */
049    public class ReleaseLocalServiceImpl extends ReleaseLocalServiceBaseImpl {
050    
051            @Override
052            public Release addRelease(String servletContextName, int buildNumber) {
053                    Release release = null;
054    
055                    if (servletContextName.equals(
056                                    ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME)) {
057    
058                            release = releasePersistence.create(ReleaseConstants.DEFAULT_ID);
059                    }
060                    else {
061                            long releaseId = counterLocalService.increment();
062    
063                            release = releasePersistence.create(releaseId);
064                    }
065    
066                    Date now = new Date();
067    
068                    release.setCreateDate(now);
069                    release.setModifiedDate(now);
070                    release.setServletContextName(servletContextName);
071                    release.setBuildNumber(buildNumber);
072    
073                    if (servletContextName.equals(
074                                    ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME)) {
075    
076                            release.setTestString(ReleaseConstants.TEST_STRING);
077                    }
078    
079                    releasePersistence.update(release);
080    
081                    return release;
082            }
083    
084            @Override
085            public void createTablesAndPopulate() {
086                    try {
087                            if (_log.isInfoEnabled()) {
088                                    _log.info("Create tables and populate with default data");
089                            }
090    
091                            DB db = DBFactoryUtil.getDB();
092    
093                            db.runSQLTemplate("portal-tables.sql", false);
094                            db.runSQLTemplate("portal-data-common.sql", false);
095                            db.runSQLTemplate("portal-data-counter.sql", false);
096                            db.runSQLTemplate("portal-data-release.sql", false);
097                            db.runSQLTemplate("indexes.sql", false);
098                            db.runSQLTemplate("sequences.sql", false);
099                    }
100                    catch (Exception e) {
101                            _log.error(e, e);
102    
103                            throw new SystemException(e);
104                    }
105            }
106    
107            @Override
108            public Release fetchRelease(String servletContextName) {
109                    if (Validator.isNull(servletContextName)) {
110                            throw new IllegalArgumentException("Servlet context name is null");
111                    }
112    
113                    Release release = null;
114    
115                    if (servletContextName.equals(
116                                    ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME)) {
117    
118                            release = releasePersistence.fetchByPrimaryKey(
119                                    ReleaseConstants.DEFAULT_ID);
120                    }
121                    else {
122                            release = releasePersistence.fetchByServletContextName(
123                                    servletContextName);
124                    }
125    
126                    return release;
127            }
128    
129            @Override
130            public int getBuildNumberOrCreate() throws PortalException {
131    
132                    // Get release build number
133    
134                    Connection con = null;
135                    PreparedStatement ps = null;
136                    ResultSet rs = null;
137    
138                    try {
139                            con = DataAccess.getConnection();
140    
141                            ps = con.prepareStatement(_GET_BUILD_NUMBER);
142    
143                            ps.setLong(1, ReleaseConstants.DEFAULT_ID);
144    
145                            rs = ps.executeQuery();
146    
147                            if (rs.next()) {
148                                    int buildNumber = rs.getInt("buildNumber");
149    
150                                    if (_log.isDebugEnabled()) {
151                                            _log.debug("Build number " + buildNumber);
152                                    }
153    
154                                    DB db = DBFactoryUtil.getDB();
155    
156                                    try {
157                                            db.runSQL("alter table Release_ add state_ INTEGER");
158                                    }
159                                    catch (Exception e) {
160                                            if (_log.isDebugEnabled()) {
161                                                    _log.debug(e.getMessage());
162                                            }
163                                    }
164    
165                                    testSupportsStringCaseSensitiveQuery();
166    
167                                    return buildNumber;
168                            }
169                    }
170                    catch (Exception e) {
171                            if (_log.isWarnEnabled()) {
172                                    _log.warn(e.getMessage());
173                            }
174                    }
175                    finally {
176                            DataAccess.cleanUp(con, ps, rs);
177                    }
178    
179                    // Create tables and populate with default data
180    
181                    if (GetterUtil.getBoolean(
182                                    PropsUtil.get(PropsKeys.SCHEMA_RUN_ENABLED))) {
183    
184                            releaseLocalService.createTablesAndPopulate();
185    
186                            testSupportsStringCaseSensitiveQuery();
187    
188                            Release release = fetchRelease(
189                                    ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME);
190    
191                            return release.getBuildNumber();
192                    }
193                    else {
194                            throw new NoSuchReleaseException(
195                                    "The database needs to be populated");
196                    }
197            }
198    
199            @Override
200            public Release updateRelease(
201                            long releaseId, int buildNumber, Date buildDate, boolean verified)
202                    throws PortalException {
203    
204                    Release release = releasePersistence.findByPrimaryKey(releaseId);
205    
206                    release.setModifiedDate(new Date());
207                    release.setBuildNumber(buildNumber);
208                    release.setBuildDate(buildDate);
209                    release.setVerified(verified);
210    
211                    releasePersistence.update(release);
212    
213                    return release;
214            }
215    
216            @Override
217            public void updateRelease(
218                            String servletContextName, List<UpgradeProcess> upgradeProcesses,
219                            int buildNumber, int previousBuildNumber, boolean indexOnUpgrade)
220                    throws PortalException {
221    
222                    if (buildNumber <= 0) {
223                            _log.error(
224                                    "Skipping upgrade processes for " + servletContextName +
225                                            " because \"release.info.build.number\" is not specified");
226    
227                            return;
228                    }
229    
230                    Release release = releaseLocalService.fetchRelease(servletContextName);
231    
232                    if (release == null) {
233                            release = releaseLocalService.addRelease(
234                                    servletContextName, previousBuildNumber);
235                    }
236    
237                    if (buildNumber == release.getBuildNumber()) {
238                            if (_log.isDebugEnabled()) {
239                                    _log.debug(
240                                            "Skipping upgrade processes for " + servletContextName +
241                                                    " because it is already up to date");
242                            }
243                    }
244                    else if (buildNumber < release.getBuildNumber()) {
245                            throw new UpgradeException(
246                                    "Skipping upgrade processes for " + servletContextName +
247                                            " because you are trying to upgrade with an older version");
248                    }
249                    else {
250                            UpgradeProcessUtil.upgradeProcess(
251                                    release.getBuildNumber(), upgradeProcesses, indexOnUpgrade);
252                    }
253    
254                    releaseLocalService.updateRelease(
255                            release.getReleaseId(), buildNumber, null, true);
256            }
257    
258            @Override
259            public void updateRelease(
260                            String servletContextName, List<UpgradeProcess> upgradeProcesses,
261                            Properties unfilteredPortalProperties)
262                    throws Exception {
263    
264                    int buildNumber = GetterUtil.getInteger(
265                            unfilteredPortalProperties.getProperty(
266                                    PropsKeys.RELEASE_INFO_BUILD_NUMBER));
267                    int previousBuildNumber = GetterUtil.getInteger(
268                            unfilteredPortalProperties.getProperty(
269                                    PropsKeys.RELEASE_INFO_PREVIOUS_BUILD_NUMBER),
270                            buildNumber);
271                    boolean indexOnUpgrade = GetterUtil.getBoolean(
272                            unfilteredPortalProperties.getProperty(PropsKeys.INDEX_ON_UPGRADE),
273                            PropsValues.INDEX_ON_UPGRADE);
274    
275                    updateRelease(
276                            servletContextName, upgradeProcesses, buildNumber,
277                            previousBuildNumber, indexOnUpgrade);
278            }
279    
280            protected void testSupportsStringCaseSensitiveQuery() {
281                    DB db = DBFactoryUtil.getDB();
282    
283                    int count = testSupportsStringCaseSensitiveQuery(
284                            ReleaseConstants.TEST_STRING);
285    
286                    if (count == 0) {
287                            try {
288                                    db.runSQL(
289                                            "alter table Release_ add testString VARCHAR(1024) null");
290                            }
291                            catch (Exception e) {
292                                    if (_log.isDebugEnabled()) {
293                                            _log.debug(e.getMessage());
294                                    }
295                            }
296    
297                            try {
298                                    db.runSQL(
299                                            "update Release_ set testString = '" +
300                                                    ReleaseConstants.TEST_STRING + "'");
301                            }
302                            catch (Exception e) {
303                                    if (_log.isDebugEnabled()) {
304                                            _log.debug(e.getMessage());
305                                    }
306                            }
307    
308                            count = testSupportsStringCaseSensitiveQuery(
309                                    ReleaseConstants.TEST_STRING);
310                    }
311    
312                    if (count == 0) {
313                            throw new SystemException(
314                                    "Release_ table was not initialized properly");
315                    }
316    
317                    count = testSupportsStringCaseSensitiveQuery(
318                            StringUtil.toUpperCase(ReleaseConstants.TEST_STRING));
319    
320                    if (count == 0) {
321                            db.setSupportsStringCaseSensitiveQuery(true);
322                    }
323                    else {
324                            db.setSupportsStringCaseSensitiveQuery(false);
325                    }
326            }
327    
328            protected int testSupportsStringCaseSensitiveQuery(String testString) {
329                    int count = 0;
330    
331                    Connection con = null;
332                    PreparedStatement ps = null;
333                    ResultSet rs = null;
334    
335                    try {
336                            con = DataAccess.getConnection();
337    
338                            ps = con.prepareStatement(_TEST_DATABASE_STRING_CASE_SENSITIVITY);
339    
340                            ps.setLong(1, ReleaseConstants.DEFAULT_ID);
341                            ps.setString(2, testString);
342    
343                            rs = ps.executeQuery();
344    
345                            if (rs.next()) {
346                                    count = rs.getInt(1);
347                            }
348                    }
349                    catch (Exception e) {
350                            if (_log.isWarnEnabled()) {
351                                    _log.warn(e.getMessage());
352                            }
353                    }
354                    finally {
355                            DataAccess.cleanUp(con, ps, rs);
356                    }
357    
358                    return count;
359            }
360    
361            private static final String _GET_BUILD_NUMBER =
362                    "select buildNumber from Release_ where releaseId = ?";
363    
364            private static final String _TEST_DATABASE_STRING_CASE_SENSITIVITY =
365                    "select count(*) from Release_ where releaseId = ? and testString = ?";
366    
367            private static final Log _log = LogFactoryUtil.getLog(
368                    ReleaseLocalServiceImpl.class);
369    
370    }