1
14
15 package com.liferay.portal.service.impl;
16
17 import com.liferay.portal.OldServiceComponentException;
18 import com.liferay.portal.dao.shard.ShardUtil;
19 import com.liferay.portal.kernel.cache.CacheRegistry;
20 import com.liferay.portal.kernel.dao.db.DB;
21 import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
22 import com.liferay.portal.kernel.dao.orm.EntityCacheUtil;
23 import com.liferay.portal.kernel.dao.orm.FinderCacheUtil;
24 import com.liferay.portal.kernel.exception.PortalException;
25 import com.liferay.portal.kernel.exception.SystemException;
26 import com.liferay.portal.kernel.log.Log;
27 import com.liferay.portal.kernel.log.LogFactoryUtil;
28 import com.liferay.portal.kernel.upgrade.util.UpgradeTable;
29 import com.liferay.portal.kernel.upgrade.util.UpgradeTableFactoryUtil;
30 import com.liferay.portal.kernel.util.HttpUtil;
31 import com.liferay.portal.kernel.util.StringPool;
32 import com.liferay.portal.kernel.util.StringUtil;
33 import com.liferay.portal.kernel.xml.Document;
34 import com.liferay.portal.kernel.xml.DocumentException;
35 import com.liferay.portal.kernel.xml.Element;
36 import com.liferay.portal.kernel.xml.SAXReaderUtil;
37 import com.liferay.portal.model.Company;
38 import com.liferay.portal.model.ModelHintsUtil;
39 import com.liferay.portal.model.ServiceComponent;
40 import com.liferay.portal.service.base.ServiceComponentLocalServiceBaseImpl;
41 import com.liferay.portal.tools.servicebuilder.Entity;
42 import com.liferay.portal.util.PropsValues;
43
44 import java.io.IOException;
45
46 import java.lang.reflect.Field;
47
48 import java.util.ArrayList;
49 import java.util.Iterator;
50 import java.util.List;
51
52 import javax.servlet.ServletContext;
53
54
60 public class ServiceComponentLocalServiceImpl
61 extends ServiceComponentLocalServiceBaseImpl {
62
63 public void destroyServiceComponent(
64 ServletContext servletContext, ClassLoader classLoader)
65 throws SystemException {
66
67 try {
68 clearCacheRegistry(servletContext);
69 }
70 catch (Exception e) {
71 throw new SystemException(e);
72 }
73 }
74
75 public ServiceComponent initServiceComponent(
76 ServletContext servletContext, ClassLoader classLoader,
77 String buildNamespace, long buildNumber, long buildDate,
78 boolean buildAutoUpgrade)
79 throws PortalException, SystemException {
80
81 try {
82 ModelHintsUtil.read(
83 classLoader, "META-INF/portlet-model-hints.xml");
84 }
85 catch (Exception e) {
86 throw new SystemException(e);
87 }
88
89 try {
90 ModelHintsUtil.read(
91 classLoader, "META-INF/portlet-model-hints-ext.xml");
92 }
93 catch (Exception e) {
94 throw new SystemException(e);
95 }
96
97 ServiceComponent serviceComponent = null;
98 ServiceComponent previousServiceComponent = null;
99
100 List<ServiceComponent> serviceComponents =
101 serviceComponentPersistence.findByBuildNamespace(
102 buildNamespace, 0, 1);
103
104 if (serviceComponents.size() == 0) {
105 long serviceComponentId = counterLocalService.increment();
106
107 serviceComponent = serviceComponentPersistence.create(
108 serviceComponentId);
109
110 serviceComponent.setBuildNamespace(buildNamespace);
111 serviceComponent.setBuildNumber(buildNumber);
112 serviceComponent.setBuildDate(buildDate);
113 }
114 else {
115 serviceComponent = serviceComponents.get(0);
116
117 if (serviceComponent.getBuildNumber() < buildNumber) {
118 previousServiceComponent = serviceComponent;
119
120 long serviceComponentId = counterLocalService.increment();
121
122 serviceComponent = serviceComponentPersistence.create(
123 serviceComponentId);
124
125 serviceComponent.setBuildNamespace(buildNamespace);
126 serviceComponent.setBuildNumber(buildNumber);
127 serviceComponent.setBuildDate(buildDate);
128 }
129 else if (serviceComponent.getBuildNumber() > buildNumber) {
130 throw new OldServiceComponentException(
131 "Build namespace " + buildNamespace + " has build number " +
132 serviceComponent.getBuildNumber() +
133 " which is newer than " + buildNumber);
134 }
135 else {
136 return serviceComponent;
137 }
138 }
139
140 try {
141 Document doc = SAXReaderUtil.createDocument(StringPool.UTF8);
142
143 Element data = doc.addElement("data");
144
145 String tablesSQL = HttpUtil.URLtoString(servletContext.getResource(
146 "/WEB-INF/sql/tables.sql"));
147
148 data.addElement("tables-sql").addCDATA(tablesSQL);
149
150 String sequencesSQL = HttpUtil.URLtoString(
151 servletContext.getResource("/WEB-INF/sql/sequences.sql"));
152
153 data.addElement("sequences-sql").addCDATA(sequencesSQL);
154
155 String indexesSQL = HttpUtil.URLtoString(servletContext.getResource(
156 "/WEB-INF/sql/indexes.sql"));
157
158 data.addElement("indexes-sql").addCDATA(indexesSQL);
159
160 String dataXML = doc.formattedString();
161
162 serviceComponent.setData(dataXML);
163
164 serviceComponentPersistence.update(serviceComponent, false);
165
166 serviceComponentLocalService.upgradeDB(
167 classLoader, buildNamespace, buildNumber, buildAutoUpgrade,
168 previousServiceComponent, tablesSQL, sequencesSQL, indexesSQL);
169
170 removeOldServiceComponents(buildNamespace);
171
172 return serviceComponent;
173 }
174 catch (Exception e) {
175 throw new SystemException(e);
176 }
177 }
178
179 public void upgradeDB(
180 ClassLoader classLoader, String buildNamespace, long buildNumber,
181 boolean buildAutoUpgrade, ServiceComponent previousServiceComponent,
182 String tablesSQL, String sequencesSQL, String indexesSQL)
183 throws Exception {
184
185 DB db = DBFactoryUtil.getDB();
186
187 if (previousServiceComponent == null) {
188 if (_log.isInfoEnabled()) {
189 _log.info("Running " + buildNamespace + " SQL scripts");
190 }
191
192 db.runSQLTemplateString(tablesSQL, true, false);
193 db.runSQLTemplateString(sequencesSQL, true, false);
194 db.runSQLTemplateString(indexesSQL, true, false);
195 }
196 else if (buildAutoUpgrade) {
197 if (_log.isInfoEnabled()) {
198 _log.info(
199 "Upgrading " + buildNamespace +
200 " database to build number " + buildNumber);
201 }
202
203 if (!tablesSQL.equals(
204 previousServiceComponent.getTablesSQL())) {
205
206 if (_log.isInfoEnabled()) {
207 _log.info("Upgrading database with tables.sql");
208 }
209
210 db.runSQLTemplateString(tablesSQL, true, false);
211
212 upgradeModels(classLoader);
213 }
214
215 if (!sequencesSQL.equals(
216 previousServiceComponent.getSequencesSQL())) {
217
218 if (_log.isInfoEnabled()) {
219 _log.info("Upgrading database with sequences.sql");
220 }
221
222 db.runSQLTemplateString(sequencesSQL, true, false);
223 }
224
225 if (!indexesSQL.equals(
226 previousServiceComponent.getIndexesSQL())) {
227
228 if (_log.isInfoEnabled()) {
229 _log.info("Upgrading database with indexes.sql");
230 }
231
232 db.runSQLTemplateString(indexesSQL, true, false);
233 }
234 }
235 }
236
237 public void verifyDB() throws PortalException, SystemException {
238 Company defaultCompany = companyPersistence.findByWebId(
239 PropsValues.COMPANY_DEFAULT_WEB_ID);
240
241 ShardUtil.pushCompanyService(defaultCompany.getCompanyId());
242
243 List<ServiceComponent> serviceComponents = null;
244
245 try {
246 serviceComponents = serviceComponentPersistence.findAll();
247 }
248 finally {
249 ShardUtil.popCompanyService();
250 }
251
252 for (ServiceComponent serviceComponent : serviceComponents) {
253 String buildNamespace = serviceComponent.getBuildNamespace();
254 String tablesSQL = serviceComponent.getTablesSQL();
255 String sequencesSQL = serviceComponent.getSequencesSQL();
256 String indexesSQL = serviceComponent.getIndexesSQL();
257
258 try {
259 serviceComponentLocalService.upgradeDB(
260 null, buildNamespace, 0, false, null, tablesSQL,
261 sequencesSQL, indexesSQL);
262 }
263 catch (Exception e) {
264 _log.error(e, e);
265 }
266 }
267 }
268
269 protected void clearCacheRegistry(ServletContext servletContext)
270 throws DocumentException, IOException {
271
272 String xml = HttpUtil.URLtoString(
273 servletContext.getResource(
274 "/WEB-INF/classes/META-INF/portlet-hbm.xml"));
275
276 if (xml == null) {
277 return;
278 }
279
280 Document doc = SAXReaderUtil.read(xml);
281
282 Element root = doc.getRootElement();
283
284 List<Element> classEls = root.elements("class");
285
286 for (Element classEl : classEls) {
287 String name = classEl.attributeValue("name");
288
289 CacheRegistry.unregister(name);
290 }
291
292 CacheRegistry.clear();
293
294 EntityCacheUtil.clearCache();
295 FinderCacheUtil.clearCache();
296 }
297
298 protected List<String> getModels(ClassLoader classLoader)
299 throws DocumentException, IOException {
300
301 List<String> models = new ArrayList<String>();
302
303 String xml = StringUtil.read(
304 classLoader, "META-INF/portlet-model-hints.xml");
305
306 models.addAll(getModels(xml));
307
308 try {
309 xml = StringUtil.read(
310 classLoader, "META-INF/portlet-model-hints-ext.xml");
311
312 models.addAll(getModels(xml));
313 }
314 catch (Exception e) {
315 if (_log.isInfoEnabled()) {
316 _log.info(
317 "No optional file META-INF/portlet-model-hints-ext.xml " +
318 "found");
319 }
320 }
321
322 return models;
323 }
324
325 protected List<String> getModels(String xml) throws DocumentException {
326 List<String> models = new ArrayList<String>();
327
328 Document doc = SAXReaderUtil.read(xml);
329
330 Element root = doc.getRootElement();
331
332 Iterator<Element> itr = root.elements("model").iterator();
333
334 while (itr.hasNext()) {
335 Element modelEl = itr.next();
336
337 String name = modelEl.attributeValue("name");
338
339 models.add(name);
340 }
341
342 return models;
343 }
344
345 protected void upgradeModels(ClassLoader classLoader) throws Exception {
346 List<String> models = getModels(classLoader);
347
348 for (String name : models) {
349 int pos = name.lastIndexOf(".model.");
350
351 name =
352 name.substring(0, pos) + ".model.impl." +
353 name.substring(pos + 7) + "ModelImpl";
354
355 Class<?> modelClass = Class.forName(name, true, classLoader);
356
357 Field tableNameField = modelClass.getField("TABLE_NAME");
358 Field tableColumnsField = modelClass.getField("TABLE_COLUMNS");
359 Field tableSQLCreateField = modelClass.getField("TABLE_SQL_CREATE");
360 Field dataSourceField = modelClass.getField("DATA_SOURCE");
361
362 String tableName = (String)tableNameField.get(null);
363 Object[][] tableColumns = (Object[][])tableColumnsField.get(null);
364 String tableSQLCreate = (String)tableSQLCreateField.get(null);
365 String dataSource = (String)dataSourceField.get(null);
366
367 if (!dataSource.equals(Entity.DEFAULT_DATA_SOURCE)) {
368 continue;
369 }
370
371 UpgradeTable upgradeTable = UpgradeTableFactoryUtil.getUpgradeTable(
372 tableName, tableColumns);
373
374 upgradeTable.setCreateSQL(tableSQLCreate);
375
376 upgradeTable.updateTable();
377 }
378 }
379
380 protected void removeOldServiceComponents(String buildNamespace)
381 throws SystemException {
382
383 int serviceComponentsCount =
384 serviceComponentPersistence.countByBuildNamespace(buildNamespace);
385
386 if (serviceComponentsCount < _MAX_SERVICE_COMPONENTS) {
387 return;
388 }
389
390 List<ServiceComponent> serviceComponents =
391 serviceComponentPersistence.findByBuildNamespace(
392 buildNamespace, _MAX_SERVICE_COMPONENTS,
393 serviceComponentsCount);
394
395 for (int i = 0; i < serviceComponents.size(); i++) {
396 ServiceComponent serviceComponent = serviceComponents.get(i);
397
398 serviceComponentPersistence.remove(serviceComponent);
399 }
400 }
401
402 private static final int _MAX_SERVICE_COMPONENTS = 10;
403
404 private static Log _log = LogFactoryUtil.getLog(
405 ServiceComponentLocalServiceImpl.class);
406
407 }