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