/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.service.impl;
import com.liferay.portal.events.StartupHelperUtil;
import com.liferay.portal.kernel.dao.db.DB;
import com.liferay.portal.kernel.dao.db.DBManagerUtil;
import com.liferay.portal.kernel.dao.jdbc.DataAccess;
import com.liferay.portal.kernel.exception.NoSuchReleaseException;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.Release;
import com.liferay.portal.kernel.model.ReleaseConstants;
import com.liferay.portal.kernel.transaction.Transactional;
import com.liferay.portal.kernel.upgrade.OlderVersionException;
import com.liferay.portal.kernel.upgrade.UpgradeProcess;
import com.liferay.portal.kernel.upgrade.util.UpgradeProcessUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.PropsKeys;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.service.base.ReleaseLocalServiceBaseImpl;
import com.liferay.portal.util.PropsUtil;
import com.liferay.portal.util.PropsValues;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Date;
import java.util.List;
import java.util.Properties;
/**
* @author Brian Wing Shun Chan
*/
public class ReleaseLocalServiceImpl extends ReleaseLocalServiceBaseImpl {
@Override
public Release addRelease(String servletContextName, int buildNumber) {
Release release = null;
if (servletContextName.equals(
ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME)) {
release = releasePersistence.create(ReleaseConstants.DEFAULT_ID);
}
else {
long releaseId = counterLocalService.increment();
release = releasePersistence.create(releaseId);
}
Date now = new Date();
release.setCreateDate(now);
release.setModifiedDate(now);
release.setServletContextName(servletContextName);
release.setBuildNumber(buildNumber);
if (servletContextName.equals(
ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME)) {
release.setTestString(ReleaseConstants.TEST_STRING);
}
releasePersistence.update(release);
return release;
}
@Override
public Release addRelease(String servletContextName, String schemaVersion) {
Release release = null;
if (servletContextName.equals(
ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME)) {
release = releasePersistence.create(ReleaseConstants.DEFAULT_ID);
}
else {
long releaseId = counterLocalService.increment();
release = releasePersistence.create(releaseId);
}
Date now = new Date();
release.setCreateDate(now);
release.setModifiedDate(now);
release.setServletContextName(servletContextName);
release.setSchemaVersion(schemaVersion);
if (servletContextName.equals(
ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME)) {
release.setTestString(ReleaseConstants.TEST_STRING);
}
releasePersistence.update(release);
return release;
}
@Override
public void createTablesAndPopulate() {
try {
if (_log.isInfoEnabled()) {
_log.info("Create tables and populate with default data");
}
DB db = DBManagerUtil.getDB();
db.runSQLTemplate("portal-tables.sql", false);
db.runSQLTemplate("portal-data-common.sql", false);
db.runSQLTemplate("portal-data-counter.sql", false);
db.runSQLTemplate("portal-data-release.sql", false);
db.runSQLTemplate("indexes.sql", false);
db.runSQLTemplate("sequences.sql", false);
StartupHelperUtil.setDbNew(true);
}
catch (Exception e) {
_log.error(e, e);
throw new SystemException(e);
}
}
@Override
public Release fetchRelease(String servletContextName) {
if (Validator.isNull(servletContextName)) {
throw new IllegalArgumentException("Servlet context name is null");
}
Release release = null;
if (servletContextName.equals(
ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME)) {
release = releasePersistence.fetchByPrimaryKey(
ReleaseConstants.DEFAULT_ID);
}
else {
release = releasePersistence.fetchByServletContextName(
servletContextName);
}
return release;
}
@Override
@Transactional
public int getBuildNumberOrCreate() throws PortalException {
// Gracefully add version column
DB db = DBManagerUtil.getDB();
try {
db.runSQL(
"alter table Release_ add schemaVersion VARCHAR(75) null");
populateVersion();
}
catch (Exception e) {
if (_log.isDebugEnabled()) {
_log.debug(e.getMessage());
}
}
// Get release build number
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = DataAccess.getConnection();
ps = con.prepareStatement(_GET_BUILD_NUMBER);
ps.setLong(1, ReleaseConstants.DEFAULT_ID);
rs = ps.executeQuery();
if (rs.next()) {
int buildNumber = rs.getInt("buildNumber");
if (_log.isDebugEnabled()) {
_log.debug("Build number " + buildNumber);
}
// Gracefully add state_ column
try {
db.runSQL("alter table Release_ add state_ INTEGER");
}
catch (Exception e) {
if (_log.isDebugEnabled()) {
_log.debug(e.getMessage());
}
}
testSupportsStringCaseSensitiveQuery();
return buildNumber;
}
}
catch (Exception e) {
if (_log.isWarnEnabled()) {
_log.warn(e.getMessage());
}
}
finally {
DataAccess.cleanUp(con, ps, rs);
}
// Create tables and populate with default data
if (GetterUtil.getBoolean(
PropsUtil.get(PropsKeys.SCHEMA_RUN_ENABLED))) {
releaseLocalService.createTablesAndPopulate();
testSupportsStringCaseSensitiveQuery();
Release release = fetchRelease(
ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME);
return release.getBuildNumber();
}
else {
throw new NoSuchReleaseException(
"The database needs to be populated");
}
}
@Override
public Release updateRelease(
long releaseId, String schemaVersion, int buildNumber,
Date buildDate, boolean verified)
throws PortalException {
Release release = releasePersistence.findByPrimaryKey(releaseId);
release.setModifiedDate(new Date());
release.setSchemaVersion(schemaVersion);
release.setBuildNumber(buildNumber);
release.setBuildDate(buildDate);
release.setVerified(verified);
releasePersistence.update(release);
return release;
}
@Override
public void updateRelease(
String servletContextName, List<UpgradeProcess> upgradeProcesses,
int buildNumber, int previousBuildNumber, boolean indexOnUpgrade)
throws PortalException {
if (buildNumber <= 0) {
_log.error(
"Skipping upgrade processes for " + servletContextName +
" because \"release.info.build.number\" is not specified");
return;
}
Release release = releaseLocalService.fetchRelease(servletContextName);
if (release == null) {
release = releaseLocalService.addRelease(
servletContextName, previousBuildNumber);
}
if (buildNumber == release.getBuildNumber()) {
if (_log.isDebugEnabled()) {
_log.debug(
"Skipping upgrade processes for " + servletContextName +
" because it is already up to date");
}
}
else if (buildNumber < release.getBuildNumber()) {
throw new OlderVersionException(
"Skipping upgrade processes for " + servletContextName +
" because you are trying to upgrade with an older version");
}
else {
UpgradeProcessUtil.upgradeProcess(
release.getBuildNumber(), upgradeProcesses, indexOnUpgrade);
}
releaseLocalService.updateRelease(
release.getReleaseId(), release.getSchemaVersion(), buildNumber,
null, true);
}
@Override
public void updateRelease(
String servletContextName, List<UpgradeProcess> upgradeProcesses,
Properties unfilteredPortalProperties)
throws Exception {
int buildNumber = GetterUtil.getInteger(
unfilteredPortalProperties.getProperty(
PropsKeys.RELEASE_INFO_BUILD_NUMBER));
int previousBuildNumber = GetterUtil.getInteger(
unfilteredPortalProperties.getProperty(
PropsKeys.RELEASE_INFO_PREVIOUS_BUILD_NUMBER),
buildNumber);
boolean indexOnUpgrade = GetterUtil.getBoolean(
unfilteredPortalProperties.getProperty(PropsKeys.INDEX_ON_UPGRADE),
PropsValues.INDEX_ON_UPGRADE);
updateRelease(
servletContextName, upgradeProcesses, buildNumber,
previousBuildNumber, indexOnUpgrade);
}
@Override
public void updateRelease(
String servletContextName, String schemaVersion,
String previousSchemaVersion) {
Release release = releaseLocalService.fetchRelease(servletContextName);
if (release == null) {
if (previousSchemaVersion.equals("0.0.0")) {
release = releaseLocalService.addRelease(
servletContextName, previousSchemaVersion);
}
else {
throw new IllegalStateException(
"Unable to update release because it does not exist");
}
}
String currentSchemaVersion = release.getSchemaVersion();
if (Validator.isNull(currentSchemaVersion)) {
currentSchemaVersion = "0.0.0";
}
if (!previousSchemaVersion.equals(currentSchemaVersion)) {
StringBundler sb = new StringBundler(5);
sb.append("Unable to update release because the previous schema ");
sb.append("version ");
sb.append(previousSchemaVersion);
sb.append(" does not match the expected schema version ");
sb.append(currentSchemaVersion);
throw new IllegalStateException(sb.toString());
}
release.setSchemaVersion(schemaVersion);
releasePersistence.update(release);
}
protected void populateVersion() {
// This method is called if and only if the version column did not
// previously exist and was safely added to the database
}
protected void testSupportsStringCaseSensitiveQuery() {
DB db = DBManagerUtil.getDB();
int count = testSupportsStringCaseSensitiveQuery(
ReleaseConstants.TEST_STRING);
if (count == 0) {
try {
db.runSQL(
"alter table Release_ add testString VARCHAR(1024) null");
}
catch (Exception e) {
if (_log.isDebugEnabled()) {
_log.debug(e.getMessage());
}
}
try {
db.runSQL(
"update Release_ set testString = '" +
ReleaseConstants.TEST_STRING + "'");
}
catch (Exception e) {
if (_log.isDebugEnabled()) {
_log.debug(e.getMessage());
}
}
count = testSupportsStringCaseSensitiveQuery(
ReleaseConstants.TEST_STRING);
}
if (count == 0) {
throw new SystemException(
"Release_ table was not initialized properly");
}
count = testSupportsStringCaseSensitiveQuery(
StringUtil.toUpperCase(ReleaseConstants.TEST_STRING));
if (count == 0) {
db.setSupportsStringCaseSensitiveQuery(true);
}
else {
db.setSupportsStringCaseSensitiveQuery(false);
}
}
protected int testSupportsStringCaseSensitiveQuery(String testString) {
int count = 0;
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = DataAccess.getConnection();
ps = con.prepareStatement(_TEST_DATABASE_STRING_CASE_SENSITIVITY);
ps.setLong(1, ReleaseConstants.DEFAULT_ID);
ps.setString(2, testString);
rs = ps.executeQuery();
if (rs.next()) {
count = rs.getInt(1);
}
}
catch (Exception e) {
if (_log.isWarnEnabled()) {
_log.warn(e.getMessage());
}
}
finally {
DataAccess.cleanUp(con, ps, rs);
}
return count;
}
private static final String _GET_BUILD_NUMBER =
"select buildNumber from Release_ where releaseId = ?";
private static final String _TEST_DATABASE_STRING_CASE_SENSITIVITY =
"select count(*) from Release_ where releaseId = ? and testString = ?";
private static final Log _log = LogFactoryUtil.getLog(
ReleaseLocalServiceImpl.class);
}