001: /**
002: * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
003: *
004: * Permission is hereby granted, free of charge, to any person obtaining a copy
005: * of this software and associated documentation files (the "Software"), to deal
006: * in the Software without restriction, including without limitation the rights
007: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008: * copies of the Software, and to permit persons to whom the Software is
009: * furnished to do so, subject to the following conditions:
010: *
011: * The above copyright notice and this permission notice shall be included in
012: * all copies or substantial portions of the Software.
013: *
014: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
017: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
019: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
020: * SOFTWARE.
021: */package com.liferay.portal.service.impl;
022:
023: import com.liferay.portal.OldServiceComponentException;
024: import com.liferay.portal.PortalException;
025: import com.liferay.portal.SystemException;
026: import com.liferay.portal.kernel.util.StringUtil;
027: import com.liferay.portal.model.ServiceComponent;
028: import com.liferay.portal.service.base.ServiceComponentLocalServiceBaseImpl;
029: import com.liferay.portal.tools.sql.DBUtil;
030: import com.liferay.portal.upgrade.util.DefaultUpgradeTableImpl;
031: import com.liferay.portal.upgrade.util.UpgradeTable;
032: import com.liferay.util.Http;
033: import com.liferay.util.xml.XMLFormatter;
034:
035: import java.io.IOException;
036: import java.io.StringReader;
037:
038: import java.lang.reflect.Field;
039:
040: import java.util.ArrayList;
041: import java.util.Iterator;
042: import java.util.List;
043:
044: import javax.servlet.ServletContext;
045:
046: import org.apache.commons.logging.Log;
047: import org.apache.commons.logging.LogFactory;
048:
049: import org.dom4j.Document;
050: import org.dom4j.DocumentException;
051: import org.dom4j.DocumentFactory;
052: import org.dom4j.Element;
053: import org.dom4j.io.SAXReader;
054:
055: /**
056: * <a href="ServiceComponentLocalServiceImpl.java.html"><b><i>View Source</i>
057: * </b></a>
058: *
059: * @author Brian Wing Shun Chan
060: *
061: */
062: public class ServiceComponentLocalServiceImpl extends
063: ServiceComponentLocalServiceBaseImpl {
064:
065: public ServiceComponent updateServiceComponent(ServletContext ctx,
066: ClassLoader portletClassLoader, String buildNamespace,
067: long buildNumber, long buildDate) throws PortalException,
068: SystemException {
069:
070: ServiceComponent serviceComponent = null;
071: ServiceComponent previousServiceComponent = null;
072:
073: List serviceComponents = serviceComponentPersistence
074: .findByBuildNamespace(buildNamespace, 0, 1);
075:
076: if (serviceComponents.size() == 0) {
077: long serviceComponentId = counterLocalService.increment();
078:
079: serviceComponent = serviceComponentPersistence
080: .create(serviceComponentId);
081:
082: serviceComponent.setBuildNamespace(buildNamespace);
083: serviceComponent.setBuildNumber(buildNumber);
084: serviceComponent.setBuildDate(buildDate);
085: } else {
086: serviceComponent = (ServiceComponent) serviceComponents
087: .get(0);
088:
089: if (serviceComponent.getBuildNumber() < buildNumber) {
090: previousServiceComponent = serviceComponent;
091:
092: long serviceComponentId = counterLocalService
093: .increment();
094:
095: serviceComponent = serviceComponentPersistence
096: .create(serviceComponentId);
097:
098: serviceComponent.setBuildNamespace(buildNamespace);
099: serviceComponent.setBuildNumber(buildNumber);
100: serviceComponent.setBuildDate(buildDate);
101: } else if (serviceComponent.getBuildNumber() > buildNumber) {
102: throw new OldServiceComponentException(
103: "Build namespace " + buildNamespace
104: + " has build number "
105: + serviceComponent.getBuildNumber()
106: + " which is newer than " + buildNumber);
107: } else {
108: return serviceComponent;
109: }
110: }
111:
112: try {
113: DocumentFactory docFactory = DocumentFactory.getInstance();
114:
115: Document doc = docFactory.createDocument("UTF-8");
116:
117: Element data = doc.addElement("data");
118:
119: String tablesSQL = Http.URLtoString(ctx
120: .getResource("/WEB-INF/sql/tables.sql"));
121:
122: data.addElement("tables-sql").addCDATA(tablesSQL);
123:
124: String sequencesSQL = Http.URLtoString(ctx
125: .getResource("/WEB-INF/sql/sequences.sql"));
126:
127: data.addElement("sequences-sql").addCDATA(sequencesSQL);
128:
129: String indexesSQL = Http.URLtoString(ctx
130: .getResource("/WEB-INF/sql/indexes.sql"));
131:
132: data.addElement("indexes-sql").addCDATA(indexesSQL);
133:
134: String dataXML = XMLFormatter.toString(doc);
135:
136: serviceComponent.setData(dataXML);
137:
138: serviceComponentPersistence.update(serviceComponent);
139:
140: upgradeDB(portletClassLoader, buildNamespace, buildNumber,
141: previousServiceComponent, tablesSQL, sequencesSQL,
142: indexesSQL);
143:
144: removeOldServiceComponents(buildNamespace);
145:
146: return serviceComponent;
147: } catch (Exception e) {
148: throw new SystemException(e);
149: }
150: }
151:
152: protected List getModels(ClassLoader portletClassLoader)
153: throws DocumentException, IOException {
154:
155: List models = new ArrayList();
156:
157: String xml = StringUtil.read(portletClassLoader,
158: "META-INF/portlet-model-hints.xml");
159:
160: SAXReader reader = new SAXReader();
161:
162: Document doc = reader.read(new StringReader(xml));
163:
164: Element root = doc.getRootElement();
165:
166: Iterator itr = root.elements("model").iterator();
167:
168: while (itr.hasNext()) {
169: Element modelEl = (Element) itr.next();
170:
171: String name = modelEl.attributeValue("name");
172:
173: models.add(name);
174: }
175:
176: return models;
177: }
178:
179: protected void upgradeDB(ClassLoader portletClassLoader,
180: String buildNamespace, long buildNumber,
181: ServiceComponent previousServiceComponent,
182: String tablesSQL, String sequencesSQL, String indexesSQL)
183: throws Exception {
184:
185: DBUtil dbUtil = DBUtil.getInstance();
186:
187: if (previousServiceComponent == null) {
188: if (_log.isInfoEnabled()) {
189: _log.info("Running " + buildNamespace
190: + " SQL scripts for the first time");
191: }
192:
193: dbUtil.runSQLTemplateString(tablesSQL, true, true);
194: dbUtil.runSQLTemplateString(sequencesSQL, true, true);
195: dbUtil.runSQLTemplateString(indexesSQL, true, true);
196: } else {
197: if (_log.isInfoEnabled()) {
198: _log.info("Upgrading " + buildNamespace
199: + " database to build number " + buildNumber);
200: }
201:
202: if (!tablesSQL.equals(previousServiceComponent
203: .getTablesSQL())) {
204:
205: if (_log.isInfoEnabled()) {
206: _log.info("Upgrading database with tables.sql");
207: }
208:
209: dbUtil.runSQLTemplateString(tablesSQL, true, false);
210:
211: upgradeModels(portletClassLoader);
212: }
213:
214: if (!sequencesSQL.equals(previousServiceComponent
215: .getSequencesSQL())) {
216:
217: if (_log.isInfoEnabled()) {
218: _log.info("Upgrading database with sequences.sql");
219: }
220:
221: dbUtil.runSQLTemplateString(sequencesSQL, true, false);
222: }
223:
224: if (!indexesSQL.equals(previousServiceComponent
225: .getIndexesSQL())) {
226:
227: if (_log.isInfoEnabled()) {
228: _log.info("Upgrading database with indexes.sql");
229: }
230:
231: dbUtil.runSQLTemplateString(indexesSQL, true, false);
232: }
233: }
234: }
235:
236: protected void upgradeModels(ClassLoader portletClassLoader)
237: throws Exception {
238:
239: List models = getModels(portletClassLoader);
240:
241: for (int i = 0; i < models.size(); i++) {
242: String name = (String) models.get(i);
243:
244: int pos = name.lastIndexOf(".model.");
245:
246: name = name.substring(0, pos) + ".model.impl."
247: + name.substring(pos + 7) + "ModelImpl";
248:
249: Class modelClass = Class.forName(name, true,
250: portletClassLoader);
251:
252: Field tableNameField = modelClass.getField("TABLE_NAME");
253: Field tableColumnsField = modelClass
254: .getField("TABLE_COLUMNS");
255: Field tableSQLCreateField = modelClass
256: .getField("TABLE_SQL_CREATE");
257:
258: String tableName = (String) tableNameField.get(null);
259: Object[][] tableColumns = (Object[][]) tableColumnsField
260: .get(null);
261: String tableSQLCreate = (String) tableSQLCreateField
262: .get(null);
263:
264: UpgradeTable upgradeTable = new DefaultUpgradeTableImpl(
265: tableName, tableColumns);
266:
267: upgradeTable.setCreateSQL(tableSQLCreate);
268:
269: upgradeTable.updateTable();
270: }
271: }
272:
273: protected void removeOldServiceComponents(String buildNamespace)
274: throws SystemException {
275:
276: int serviceComponentsCount = serviceComponentPersistence
277: .countByBuildNamespace(buildNamespace);
278:
279: if (serviceComponentsCount < _MAX_SERVICE_COMPONENTS) {
280: return;
281: }
282:
283: List serviceComponents = serviceComponentPersistence
284: .findByBuildNamespace(buildNamespace,
285: _MAX_SERVICE_COMPONENTS, serviceComponentsCount);
286:
287: for (int i = 0; i < serviceComponents.size(); i++) {
288: ServiceComponent serviceComponent = (ServiceComponent) serviceComponents
289: .get(i);
290:
291: serviceComponentPersistence.remove(serviceComponent);
292: }
293: }
294:
295: private static final int _MAX_SERVICE_COMPONENTS = 10;
296:
297: private static Log _log = LogFactory
298: .getLog(ServiceComponentLocalServiceImpl.class);
299:
300: }
|