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.upgrade.util.UpgradeTableListener;
030 import com.liferay.portal.kernel.util.HttpUtil;
031 import com.liferay.portal.kernel.util.InstanceFactory;
032 import com.liferay.portal.kernel.util.StringPool;
033 import com.liferay.portal.kernel.util.StringUtil;
034 import com.liferay.portal.kernel.xml.Document;
035 import com.liferay.portal.kernel.xml.DocumentException;
036 import com.liferay.portal.kernel.xml.Element;
037 import com.liferay.portal.kernel.xml.SAXReaderUtil;
038 import com.liferay.portal.model.ModelHintsUtil;
039 import com.liferay.portal.model.ServiceComponent;
040 import com.liferay.portal.security.lang.PortalSecurityManagerThreadLocal;
041 import com.liferay.portal.security.pacl.PACLPolicy;
042 import com.liferay.portal.security.pacl.PACLPolicyManager;
043 import com.liferay.portal.service.base.ServiceComponentLocalServiceBaseImpl;
044 import com.liferay.portal.tools.servicebuilder.Entity;
045
046 import java.io.IOException;
047 import java.io.InputStream;
048
049 import java.lang.reflect.Field;
050
051 import java.util.ArrayList;
052 import java.util.List;
053
054 import javax.servlet.ServletContext;
055
056
059 public class ServiceComponentLocalServiceImpl
060 extends ServiceComponentLocalServiceBaseImpl {
061
062 public void destroyServiceComponent(
063 ServletContext servletContext, ClassLoader classLoader)
064 throws SystemException {
065
066 try {
067 clearCacheRegistry(servletContext);
068 }
069 catch (Exception e) {
070 throw new SystemException(e);
071 }
072 }
073
074 public ServiceComponent initServiceComponent(
075 ServletContext servletContext, ClassLoader classLoader,
076 String buildNamespace, long buildNumber, long buildDate,
077 boolean buildAutoUpgrade)
078 throws PortalException, SystemException {
079
080 try {
081 ModelHintsUtil.read(
082 classLoader, "META-INF/portlet-model-hints.xml");
083 }
084 catch (Exception e) {
085 throw new SystemException(e);
086 }
087
088 try {
089 ModelHintsUtil.read(
090 classLoader, "META-INF/portlet-model-hints-ext.xml");
091 }
092 catch (Exception e) {
093 throw new SystemException(e);
094 }
095
096 ServiceComponent serviceComponent = null;
097 ServiceComponent previousServiceComponent = null;
098
099 List<ServiceComponent> serviceComponents =
100 serviceComponentPersistence.findByBuildNamespace(
101 buildNamespace, 0, 1);
102
103 if (serviceComponents.isEmpty()) {
104 long serviceComponentId = counterLocalService.increment();
105
106 serviceComponent = serviceComponentPersistence.create(
107 serviceComponentId);
108
109 serviceComponent.setBuildNamespace(buildNamespace);
110 serviceComponent.setBuildNumber(buildNumber);
111 serviceComponent.setBuildDate(buildDate);
112 }
113 else {
114 serviceComponent = serviceComponents.get(0);
115
116 if (serviceComponent.getBuildNumber() < buildNumber) {
117 previousServiceComponent = serviceComponent;
118
119 long serviceComponentId = counterLocalService.increment();
120
121 serviceComponent = serviceComponentPersistence.create(
122 serviceComponentId);
123
124 serviceComponent.setBuildNamespace(buildNamespace);
125 serviceComponent.setBuildNumber(buildNumber);
126 serviceComponent.setBuildDate(buildDate);
127 }
128 else if (serviceComponent.getBuildNumber() > buildNumber) {
129 throw new OldServiceComponentException(
130 "Build namespace " + buildNamespace + " has build number " +
131 serviceComponent.getBuildNumber() +
132 " which is newer than " + buildNumber);
133 }
134 else {
135 return serviceComponent;
136 }
137 }
138
139 try {
140 Document document = SAXReaderUtil.createDocument(StringPool.UTF8);
141
142 Element dataElement = document.addElement("data");
143
144 Element tablesSQLElement = dataElement.addElement("tables-sql");
145
146 String tablesSQL = HttpUtil.URLtoString(
147 servletContext.getResource("/WEB-INF/sql/tables.sql"));
148
149 tablesSQLElement.addCDATA(tablesSQL);
150
151 Element sequencesSQLElement = dataElement.addElement(
152 "sequences-sql");
153
154 String sequencesSQL = HttpUtil.URLtoString(
155 servletContext.getResource("/WEB-INF/sql/sequences.sql"));
156
157 sequencesSQLElement.addCDATA(sequencesSQL);
158
159 Element indexesSQLElement = dataElement.addElement("indexes-sql");
160
161 String indexesSQL = HttpUtil.URLtoString(
162 servletContext.getResource("/WEB-INF/sql/indexes.sql"));
163
164 indexesSQLElement.addCDATA(indexesSQL);
165
166 String dataXML = document.formattedString();
167
168 serviceComponent.setData(dataXML);
169
170 serviceComponentPersistence.update(serviceComponent);
171
172 serviceComponentLocalService.upgradeDB(
173 classLoader, buildNamespace, buildNumber, buildAutoUpgrade,
174 previousServiceComponent, tablesSQL, sequencesSQL, indexesSQL);
175
176 removeOldServiceComponents(buildNamespace);
177
178 return serviceComponent;
179 }
180 catch (Exception e) {
181 throw new SystemException(e);
182 }
183 }
184
185 public void upgradeDB(
186 ClassLoader classLoader, String buildNamespace, long buildNumber,
187 boolean buildAutoUpgrade, ServiceComponent previousServiceComponent,
188 String tablesSQL, String sequencesSQL, String indexesSQL)
189 throws Exception {
190
191 PACLPolicy previousPACLPolicy =
192 PortalSecurityManagerThreadLocal.getPACLPolicy();
193
194 boolean checkGetClassLoader =
195 PortalSecurityManagerThreadLocal.isCheckGetClassLoader();
196 boolean checkReadFile =
197 PortalSecurityManagerThreadLocal.isCheckReadFile();
198
199 try {
200 PACLPolicy paclPolicy = PACLPolicyManager.getPACLPolicy(
201 classLoader);
202
203 PortalSecurityManagerThreadLocal.setPACLPolicy(paclPolicy);
204
205 PortalSecurityManagerThreadLocal.setCheckGetClassLoader(false);
206 PortalSecurityManagerThreadLocal.setCheckReadFile(false);
207
208 doUpgradeDB(
209 classLoader, buildNamespace, buildNumber, buildAutoUpgrade,
210 previousServiceComponent, tablesSQL, sequencesSQL, indexesSQL);
211 }
212 finally {
213 PortalSecurityManagerThreadLocal.setPACLPolicy(previousPACLPolicy);
214
215 PortalSecurityManagerThreadLocal.setCheckGetClassLoader(
216 checkGetClassLoader);
217 PortalSecurityManagerThreadLocal.setCheckReadFile(checkReadFile);
218 }
219 }
220
221 public void verifyDB() throws SystemException {
222 List<ServiceComponent> serviceComponents =
223 serviceComponentPersistence.findAll();
224
225 for (ServiceComponent serviceComponent : serviceComponents) {
226 String buildNamespace = serviceComponent.getBuildNamespace();
227 String tablesSQL = serviceComponent.getTablesSQL();
228 String sequencesSQL = serviceComponent.getSequencesSQL();
229 String indexesSQL = serviceComponent.getIndexesSQL();
230
231 try {
232 serviceComponentLocalService.upgradeDB(
233 null, buildNamespace, 0, false, null, tablesSQL,
234 sequencesSQL, indexesSQL);
235 }
236 catch (Exception e) {
237 _log.error(e, e);
238 }
239 }
240 }
241
242 protected void clearCacheRegistry(ServletContext servletContext)
243 throws DocumentException {
244
245 InputStream inputStream = servletContext.getResourceAsStream(
246 "/WEB-INF/classes/META-INF/portlet-hbm.xml");
247
248 if (inputStream == null) {
249 return;
250 }
251
252 Document document = SAXReaderUtil.read(inputStream);
253
254 Element rootElement = document.getRootElement();
255
256 List<Element> classElements = rootElement.elements("class");
257
258 for (Element classElement : classElements) {
259 String name = classElement.attributeValue("name");
260
261 CacheRegistryUtil.unregister(name);
262 }
263
264 CacheRegistryUtil.clear();
265
266 EntityCacheUtil.clearCache();
267 FinderCacheUtil.clearCache();
268 }
269
270 protected void doUpgradeDB(
271 ClassLoader classLoader, String buildNamespace, long buildNumber,
272 boolean buildAutoUpgrade, ServiceComponent previousServiceComponent,
273 String tablesSQL, String sequencesSQL, String indexesSQL)
274 throws Exception {
275
276 DB db = DBFactoryUtil.getDB();
277
278 if (previousServiceComponent == null) {
279 if (_log.isInfoEnabled()) {
280 _log.info("Running " + buildNamespace + " SQL scripts");
281 }
282
283 db.runSQLTemplateString(tablesSQL, true, false);
284 db.runSQLTemplateString(sequencesSQL, true, false);
285 db.runSQLTemplateString(indexesSQL, true, false);
286 }
287 else if (buildAutoUpgrade) {
288 if (_log.isInfoEnabled()) {
289 _log.info(
290 "Upgrading " + buildNamespace +
291 " database to build number " + buildNumber);
292 }
293
294 if (!tablesSQL.equals(previousServiceComponent.getTablesSQL())) {
295 if (_log.isInfoEnabled()) {
296 _log.info("Upgrading database with tables.sql");
297 }
298
299 db.runSQLTemplateString(tablesSQL, true, false);
300
301 upgradeModels(classLoader, previousServiceComponent);
302 }
303
304 if (!sequencesSQL.equals(
305 previousServiceComponent.getSequencesSQL())) {
306
307 if (_log.isInfoEnabled()) {
308 _log.info("Upgrading database with sequences.sql");
309 }
310
311 db.runSQLTemplateString(sequencesSQL, true, false);
312 }
313
314 if (!indexesSQL.equals(previousServiceComponent.getIndexesSQL())) {
315 if (_log.isInfoEnabled()) {
316 _log.info("Upgrading database with indexes.sql");
317 }
318
319 db.runSQLTemplateString(indexesSQL, true, false);
320 }
321 }
322 }
323
324 protected List<String> getModels(ClassLoader classLoader)
325 throws DocumentException, IOException {
326
327 List<String> models = new ArrayList<String>();
328
329 String xml = StringUtil.read(
330 classLoader, "META-INF/portlet-model-hints.xml");
331
332 models.addAll(getModels(xml));
333
334 try {
335 xml = StringUtil.read(
336 classLoader, "META-INF/portlet-model-hints-ext.xml");
337
338 models.addAll(getModels(xml));
339 }
340 catch (Exception e) {
341 if (_log.isInfoEnabled()) {
342 _log.info(
343 "No optional file META-INF/portlet-model-hints-ext.xml " +
344 "found");
345 }
346 }
347
348 return models;
349 }
350
351 protected List<String> getModels(String xml) throws DocumentException {
352 List<String> models = new ArrayList<String>();
353
354 Document document = SAXReaderUtil.read(xml);
355
356 Element rootElement = document.getRootElement();
357
358 List<Element> modelElements = rootElement.elements("model");
359
360 for (Element modelElement : modelElements) {
361 String name = modelElement.attributeValue("name");
362
363 models.add(name);
364 }
365
366 return models;
367 }
368
369 protected UpgradeTableListener getUpgradeTableListener(
370 ClassLoader classLoader, Class<?> modelClass) {
371
372 String modelClassName = modelClass.getName();
373
374 String upgradeTableListenerClassName = modelClassName;
375
376 upgradeTableListenerClassName = StringUtil.replaceLast(
377 upgradeTableListenerClassName, ".model.impl.", ".model.upgrade.");
378 upgradeTableListenerClassName = StringUtil.replaceLast(
379 upgradeTableListenerClassName, "ModelImpl", "UpgradeTableListener");
380
381 try {
382 UpgradeTableListener upgradeTableListener =
383 (UpgradeTableListener)InstanceFactory.newInstance(
384 classLoader, upgradeTableListenerClassName);
385
386 if (_log.isInfoEnabled()) {
387 _log.info("Instantiated " + upgradeTableListenerClassName);
388 }
389
390 return upgradeTableListener;
391 }
392 catch (Exception e) {
393 if (_log.isDebugEnabled()) {
394 _log.debug(
395 "Unable to instantiate " + upgradeTableListenerClassName);
396 }
397
398 return null;
399 }
400 }
401
402 protected void removeOldServiceComponents(String buildNamespace)
403 throws SystemException {
404
405 int serviceComponentsCount =
406 serviceComponentPersistence.countByBuildNamespace(buildNamespace);
407
408 if (serviceComponentsCount < _MAX_SERVICE_COMPONENTS) {
409 return;
410 }
411
412 List<ServiceComponent> serviceComponents =
413 serviceComponentPersistence.findByBuildNamespace(
414 buildNamespace, _MAX_SERVICE_COMPONENTS,
415 serviceComponentsCount);
416
417 for (int i = 0; i < serviceComponents.size(); i++) {
418 ServiceComponent serviceComponent = serviceComponents.get(i);
419
420 serviceComponentPersistence.remove(serviceComponent);
421 }
422 }
423
424 protected void upgradeModels(
425 ClassLoader classLoader, ServiceComponent previousServiceComponent)
426 throws Exception {
427
428 List<String> models = getModels(classLoader);
429
430 for (String name : models) {
431 int pos = name.lastIndexOf(".model.");
432
433 name =
434 name.substring(0, pos) + ".model.impl." +
435 name.substring(pos + 7) + "ModelImpl";
436
437 Class<?> modelClass = Class.forName(name, true, classLoader);
438
439 Field tableNameField = modelClass.getField("TABLE_NAME");
440 Field tableColumnsField = modelClass.getField("TABLE_COLUMNS");
441 Field tableSQLCreateField = modelClass.getField("TABLE_SQL_CREATE");
442 Field dataSourceField = modelClass.getField("DATA_SOURCE");
443
444 String tableName = (String)tableNameField.get(null);
445 Object[][] tableColumns = (Object[][])tableColumnsField.get(null);
446 String tableSQLCreate = (String)tableSQLCreateField.get(null);
447 String dataSource = (String)dataSourceField.get(null);
448
449 if (!dataSource.equals(Entity.DEFAULT_DATA_SOURCE)) {
450 continue;
451 }
452
453 UpgradeTable upgradeTable = UpgradeTableFactoryUtil.getUpgradeTable(
454 tableName, tableColumns);
455
456 UpgradeTableListener upgradeTableListener = getUpgradeTableListener(
457 classLoader, modelClass);
458
459 upgradeTable.setCreateSQL(tableSQLCreate);
460
461 if (upgradeTableListener != null) {
462 upgradeTableListener.onBeforeUpdateTable(
463 previousServiceComponent, upgradeTable);
464 }
465
466 upgradeTable.updateTable();
467
468 if (upgradeTableListener != null) {
469 upgradeTableListener.onAfterUpdateTable(
470 previousServiceComponent, upgradeTable);
471 }
472 }
473 }
474
475 private static final int _MAX_SERVICE_COMPONENTS = 10;
476
477 private static Log _log = LogFactoryUtil.getLog(
478 ServiceComponentLocalServiceImpl.class);
479
480 }