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