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