001
014
015 package com.liferay.portal.service.impl;
016
017 import com.liferay.portal.OldServiceComponentException;
018 import com.liferay.portal.kernel.cache.CacheRegistryUtil;
019 import com.liferay.portal.kernel.dao.db.DB;
020 import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
021 import com.liferay.portal.kernel.dao.orm.EntityCacheUtil;
022 import com.liferay.portal.kernel.dao.orm.FinderCacheUtil;
023 import com.liferay.portal.kernel.exception.PortalException;
024 import com.liferay.portal.kernel.exception.SystemException;
025 import com.liferay.portal.kernel.log.Log;
026 import com.liferay.portal.kernel.log.LogFactoryUtil;
027 import com.liferay.portal.kernel.upgrade.util.UpgradeTable;
028 import com.liferay.portal.kernel.upgrade.util.UpgradeTableFactoryUtil;
029 import com.liferay.portal.kernel.util.HttpUtil;
030 import com.liferay.portal.kernel.util.StringPool;
031 import com.liferay.portal.kernel.util.StringUtil;
032 import com.liferay.portal.kernel.xml.Document;
033 import com.liferay.portal.kernel.xml.DocumentException;
034 import com.liferay.portal.kernel.xml.Element;
035 import com.liferay.portal.kernel.xml.SAXReaderUtil;
036 import com.liferay.portal.model.ModelHintsUtil;
037 import com.liferay.portal.model.ServiceComponent;
038 import com.liferay.portal.service.base.ServiceComponentLocalServiceBaseImpl;
039 import com.liferay.portal.tools.servicebuilder.Entity;
040
041 import java.io.IOException;
042 import java.io.InputStream;
043
044 import java.lang.reflect.Field;
045
046 import java.util.ArrayList;
047 import java.util.List;
048
049 import javax.servlet.ServletContext;
050
051
054 public class ServiceComponentLocalServiceImpl
055 extends ServiceComponentLocalServiceBaseImpl {
056
057 public void destroyServiceComponent(
058 ServletContext servletContext, ClassLoader classLoader)
059 throws SystemException {
060
061 try {
062 clearCacheRegistry(servletContext);
063 }
064 catch (Exception e) {
065 throw new SystemException(e);
066 }
067 }
068
069 public ServiceComponent initServiceComponent(
070 ServletContext servletContext, ClassLoader classLoader,
071 String buildNamespace, long buildNumber, long buildDate,
072 boolean buildAutoUpgrade)
073 throws PortalException, SystemException {
074
075 try {
076 ModelHintsUtil.read(
077 classLoader, "META-INF/portlet-model-hints.xml");
078 }
079 catch (Exception e) {
080 throw new SystemException(e);
081 }
082
083 try {
084 ModelHintsUtil.read(
085 classLoader, "META-INF/portlet-model-hints-ext.xml");
086 }
087 catch (Exception e) {
088 throw new SystemException(e);
089 }
090
091 ServiceComponent serviceComponent = null;
092 ServiceComponent previousServiceComponent = null;
093
094 List<ServiceComponent> serviceComponents =
095 serviceComponentPersistence.findByBuildNamespace(
096 buildNamespace, 0, 1);
097
098 if (serviceComponents.size() == 0) {
099 long serviceComponentId = counterLocalService.increment();
100
101 serviceComponent = serviceComponentPersistence.create(
102 serviceComponentId);
103
104 serviceComponent.setBuildNamespace(buildNamespace);
105 serviceComponent.setBuildNumber(buildNumber);
106 serviceComponent.setBuildDate(buildDate);
107 }
108 else {
109 serviceComponent = serviceComponents.get(0);
110
111 if (serviceComponent.getBuildNumber() < buildNumber) {
112 previousServiceComponent = serviceComponent;
113
114 long serviceComponentId = counterLocalService.increment();
115
116 serviceComponent = serviceComponentPersistence.create(
117 serviceComponentId);
118
119 serviceComponent.setBuildNamespace(buildNamespace);
120 serviceComponent.setBuildNumber(buildNumber);
121 serviceComponent.setBuildDate(buildDate);
122 }
123 else if (serviceComponent.getBuildNumber() > buildNumber) {
124 throw new OldServiceComponentException(
125 "Build namespace " + buildNamespace + " has build number " +
126 serviceComponent.getBuildNumber() +
127 " which is newer than " + buildNumber);
128 }
129 else {
130 return serviceComponent;
131 }
132 }
133
134 try {
135 Document document = SAXReaderUtil.createDocument(StringPool.UTF8);
136
137 Element dataElement = document.addElement("data");
138
139 String tablesSQL = HttpUtil.URLtoString(servletContext.getResource(
140 "/WEB-INF/sql/tables.sql"));
141
142 dataElement.addElement("tables-sql").addCDATA(tablesSQL);
143
144 String sequencesSQL = HttpUtil.URLtoString(
145 servletContext.getResource("/WEB-INF/sql/sequences.sql"));
146
147 dataElement.addElement("sequences-sql").addCDATA(sequencesSQL);
148
149 String indexesSQL = HttpUtil.URLtoString(servletContext.getResource(
150 "/WEB-INF/sql/indexes.sql"));
151
152 dataElement.addElement("indexes-sql").addCDATA(indexesSQL);
153
154 String dataXML = document.formattedString();
155
156 serviceComponent.setData(dataXML);
157
158 serviceComponentPersistence.update(serviceComponent, false);
159
160 serviceComponentLocalService.upgradeDB(
161 classLoader, buildNamespace, buildNumber, buildAutoUpgrade,
162 previousServiceComponent, tablesSQL, sequencesSQL, indexesSQL);
163
164 removeOldServiceComponents(buildNamespace);
165
166 return serviceComponent;
167 }
168 catch (Exception e) {
169 throw new SystemException(e);
170 }
171 }
172
173 public void upgradeDB(
174 ClassLoader classLoader, String buildNamespace, long buildNumber,
175 boolean buildAutoUpgrade, ServiceComponent previousServiceComponent,
176 String tablesSQL, String sequencesSQL, String indexesSQL)
177 throws Exception {
178
179 DB db = DBFactoryUtil.getDB();
180
181 if (previousServiceComponent == null) {
182 if (_log.isInfoEnabled()) {
183 _log.info("Running " + buildNamespace + " SQL scripts");
184 }
185
186 db.runSQLTemplateString(tablesSQL, true, false);
187 db.runSQLTemplateString(sequencesSQL, true, false);
188 db.runSQLTemplateString(indexesSQL, true, false);
189 }
190 else if (buildAutoUpgrade) {
191 if (_log.isInfoEnabled()) {
192 _log.info(
193 "Upgrading " + buildNamespace +
194 " database to build number " + buildNumber);
195 }
196
197 if (!tablesSQL.equals(previousServiceComponent.getTablesSQL())) {
198 if (_log.isInfoEnabled()) {
199 _log.info("Upgrading database with tables.sql");
200 }
201
202 db.runSQLTemplateString(tablesSQL, true, false);
203
204 upgradeModels(classLoader);
205 }
206
207 if (!sequencesSQL.equals(
208 previousServiceComponent.getSequencesSQL())) {
209
210 if (_log.isInfoEnabled()) {
211 _log.info("Upgrading database with sequences.sql");
212 }
213
214 db.runSQLTemplateString(sequencesSQL, true, false);
215 }
216
217 if (!indexesSQL.equals(previousServiceComponent.getIndexesSQL())) {
218 if (_log.isInfoEnabled()) {
219 _log.info("Upgrading database with indexes.sql");
220 }
221
222 db.runSQLTemplateString(indexesSQL, true, false);
223 }
224 }
225 }
226
227 public void verifyDB() throws SystemException {
228 List<ServiceComponent> serviceComponents =
229 serviceComponentPersistence.findAll();
230
231 for (ServiceComponent serviceComponent : serviceComponents) {
232 String buildNamespace = serviceComponent.getBuildNamespace();
233 String tablesSQL = serviceComponent.getTablesSQL();
234 String sequencesSQL = serviceComponent.getSequencesSQL();
235 String indexesSQL = serviceComponent.getIndexesSQL();
236
237 try {
238 serviceComponentLocalService.upgradeDB(
239 null, buildNamespace, 0, false, null, tablesSQL,
240 sequencesSQL, indexesSQL);
241 }
242 catch (Exception e) {
243 _log.error(e, e);
244 }
245 }
246 }
247
248 protected void clearCacheRegistry(ServletContext servletContext)
249 throws DocumentException {
250
251 InputStream inputStream = servletContext.getResourceAsStream(
252 "/WEB-INF/classes/META-INF/portlet-hbm.xml");
253
254 if (inputStream == null) {
255 return;
256 }
257
258 Document document = SAXReaderUtil.read(inputStream);
259
260 Element rootElement = document.getRootElement();
261
262 List<Element> classElements = rootElement.elements("class");
263
264 for (Element classElement : classElements) {
265 String name = classElement.attributeValue("name");
266
267 CacheRegistryUtil.unregister(name);
268 }
269
270 CacheRegistryUtil.clear();
271
272 EntityCacheUtil.clearCache();
273 FinderCacheUtil.clearCache();
274 }
275
276 protected List<String> getModels(ClassLoader classLoader)
277 throws DocumentException, IOException {
278
279 List<String> models = new ArrayList<String>();
280
281 String xml = StringUtil.read(
282 classLoader, "META-INF/portlet-model-hints.xml");
283
284 models.addAll(getModels(xml));
285
286 try {
287 xml = StringUtil.read(
288 classLoader, "META-INF/portlet-model-hints-ext.xml");
289
290 models.addAll(getModels(xml));
291 }
292 catch (Exception e) {
293 if (_log.isInfoEnabled()) {
294 _log.info(
295 "No optional file META-INF/portlet-model-hints-ext.xml " +
296 "found");
297 }
298 }
299
300 return models;
301 }
302
303 protected List<String> getModels(String xml) throws DocumentException {
304 List<String> models = new ArrayList<String>();
305
306 Document document = SAXReaderUtil.read(xml);
307
308 Element rootElement = document.getRootElement();
309
310 List<Element> modelElements = rootElement.elements("model");
311
312 for (Element modelElement : modelElements) {
313 String name = modelElement.attributeValue("name");
314
315 models.add(name);
316 }
317
318 return models;
319 }
320
321 protected void removeOldServiceComponents(String buildNamespace)
322 throws SystemException {
323
324 int serviceComponentsCount =
325 serviceComponentPersistence.countByBuildNamespace(buildNamespace);
326
327 if (serviceComponentsCount < _MAX_SERVICE_COMPONENTS) {
328 return;
329 }
330
331 List<ServiceComponent> serviceComponents =
332 serviceComponentPersistence.findByBuildNamespace(
333 buildNamespace, _MAX_SERVICE_COMPONENTS,
334 serviceComponentsCount);
335
336 for (int i = 0; i < serviceComponents.size(); i++) {
337 ServiceComponent serviceComponent = serviceComponents.get(i);
338
339 serviceComponentPersistence.remove(serviceComponent);
340 }
341 }
342
343 protected void upgradeModels(ClassLoader classLoader) throws Exception {
344 List<String> models = getModels(classLoader);
345
346 for (String name : models) {
347 int pos = name.lastIndexOf(".model.");
348
349 name =
350 name.substring(0, pos) + ".model.impl." +
351 name.substring(pos + 7) + "ModelImpl";
352
353 Class<?> modelClass = Class.forName(name, true, classLoader);
354
355 Field tableNameField = modelClass.getField("TABLE_NAME");
356 Field tableColumnsField = modelClass.getField("TABLE_COLUMNS");
357 Field tableSQLCreateField = modelClass.getField("TABLE_SQL_CREATE");
358 Field dataSourceField = modelClass.getField("DATA_SOURCE");
359
360 String tableName = (String)tableNameField.get(null);
361 Object[][] tableColumns = (Object[][])tableColumnsField.get(null);
362 String tableSQLCreate = (String)tableSQLCreateField.get(null);
363 String dataSource = (String)dataSourceField.get(null);
364
365 if (!dataSource.equals(Entity.DEFAULT_DATA_SOURCE)) {
366 continue;
367 }
368
369 UpgradeTable upgradeTable = UpgradeTableFactoryUtil.getUpgradeTable(
370 tableName, tableColumns);
371
372 upgradeTable.setCreateSQL(tableSQLCreate);
373
374 upgradeTable.updateTable();
375 }
376 }
377
378 private static final int _MAX_SERVICE_COMPONENTS = 10;
379
380 private static Log _log = LogFactoryUtil.getLog(
381 ServiceComponentLocalServiceImpl.class);
382
383 }