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