001
014
015 package com.liferay.portal.service.impl;
016
017 import com.liferay.portal.OldServiceComponentException;
018 import com.liferay.portal.kernel.cache.CacheRegistryUtil;
019 import com.liferay.portal.kernel.dao.db.DB;
020 import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
021 import com.liferay.portal.kernel.dao.orm.EntityCacheUtil;
022 import com.liferay.portal.kernel.dao.orm.FinderCacheUtil;
023 import com.liferay.portal.kernel.exception.PortalException;
024 import com.liferay.portal.kernel.exception.SystemException;
025 import com.liferay.portal.kernel.log.Log;
026 import com.liferay.portal.kernel.log.LogFactoryUtil;
027 import com.liferay.portal.kernel.upgrade.util.UpgradeTable;
028 import com.liferay.portal.kernel.upgrade.util.UpgradeTableFactoryUtil;
029 import com.liferay.portal.kernel.util.HttpUtil;
030 import com.liferay.portal.kernel.util.StringPool;
031 import com.liferay.portal.kernel.util.StringUtil;
032 import com.liferay.portal.kernel.xml.Document;
033 import com.liferay.portal.kernel.xml.DocumentException;
034 import com.liferay.portal.kernel.xml.Element;
035 import com.liferay.portal.kernel.xml.SAXReaderUtil;
036 import com.liferay.portal.model.ModelHintsUtil;
037 import com.liferay.portal.model.ServiceComponent;
038 import com.liferay.portal.service.base.ServiceComponentLocalServiceBaseImpl;
039 import com.liferay.portal.tools.servicebuilder.Entity;
040
041 import java.io.IOException;
042 import java.io.InputStream;
043
044 import java.lang.reflect.Field;
045
046 import java.security.AccessControlContext;
047 import java.security.AccessController;
048 import java.security.PrivilegedExceptionAction;
049 import java.security.ProtectionDomain;
050
051 import java.util.ArrayList;
052 import java.util.List;
053
054 import javax.servlet.ServletContext;
055
056
059 public class ServiceComponentLocalServiceImpl
060 extends ServiceComponentLocalServiceBaseImpl {
061
062 @Override
063 public void destroyServiceComponent(
064 ServletContext servletContext, ClassLoader classLoader)
065 throws SystemException {
066
067 try {
068 clearCacheRegistry(servletContext);
069 }
070 catch (Exception e) {
071 throw new SystemException(e);
072 }
073 }
074
075 @Override
076 public ServiceComponent initServiceComponent(
077 ServletContext servletContext, ClassLoader classLoader,
078 String buildNamespace, long buildNumber, long buildDate,
079 boolean buildAutoUpgrade)
080 throws PortalException, SystemException {
081
082 try {
083 ModelHintsUtil.read(
084 classLoader, "META-INF/portlet-model-hints.xml");
085 }
086 catch (Exception e) {
087 throw new SystemException(e);
088 }
089
090 try {
091 ModelHintsUtil.read(
092 classLoader, "META-INF/portlet-model-hints-ext.xml");
093 }
094 catch (Exception e) {
095 throw new SystemException(e);
096 }
097
098 ServiceComponent serviceComponent = null;
099 ServiceComponent previousServiceComponent = null;
100
101 List<ServiceComponent> serviceComponents =
102 serviceComponentPersistence.findByBuildNamespace(
103 buildNamespace, 0, 1);
104
105 if (serviceComponents.isEmpty()) {
106 long serviceComponentId = counterLocalService.increment();
107
108 serviceComponent = serviceComponentPersistence.create(
109 serviceComponentId);
110
111 serviceComponent.setBuildNamespace(buildNamespace);
112 serviceComponent.setBuildNumber(buildNumber);
113 serviceComponent.setBuildDate(buildDate);
114 }
115 else {
116 serviceComponent = serviceComponents.get(0);
117
118 if (serviceComponent.getBuildNumber() < buildNumber) {
119 previousServiceComponent = serviceComponent;
120
121 long serviceComponentId = counterLocalService.increment();
122
123 serviceComponent = serviceComponentPersistence.create(
124 serviceComponentId);
125
126 serviceComponent.setBuildNamespace(buildNamespace);
127 serviceComponent.setBuildNumber(buildNumber);
128 serviceComponent.setBuildDate(buildDate);
129 }
130 else if (serviceComponent.getBuildNumber() > buildNumber) {
131 throw new OldServiceComponentException(
132 "Build namespace " + buildNamespace + " has build number " +
133 serviceComponent.getBuildNumber() +
134 " which is newer than " + buildNumber);
135 }
136 else {
137 return serviceComponent;
138 }
139 }
140
141 try {
142 Document document = SAXReaderUtil.createDocument(StringPool.UTF8);
143
144 Element dataElement = document.addElement("data");
145
146 Element tablesSQLElement = dataElement.addElement("tables-sql");
147
148 String tablesSQL = HttpUtil.URLtoString(
149 servletContext.getResource("/WEB-INF/sql/tables.sql"));
150
151 tablesSQLElement.addCDATA(tablesSQL);
152
153 Element sequencesSQLElement = dataElement.addElement(
154 "sequences-sql");
155
156 String sequencesSQL = HttpUtil.URLtoString(
157 servletContext.getResource("/WEB-INF/sql/sequences.sql"));
158
159 sequencesSQLElement.addCDATA(sequencesSQL);
160
161 Element indexesSQLElement = dataElement.addElement("indexes-sql");
162
163 String indexesSQL = HttpUtil.URLtoString(
164 servletContext.getResource("/WEB-INF/sql/indexes.sql"));
165
166 indexesSQLElement.addCDATA(indexesSQL);
167
168 String dataXML = document.formattedString();
169
170 serviceComponent.setData(dataXML);
171
172 serviceComponentPersistence.update(serviceComponent, false);
173
174 serviceComponentLocalService.upgradeDB(
175 classLoader, buildNamespace, buildNumber, buildAutoUpgrade,
176 previousServiceComponent, tablesSQL, sequencesSQL, indexesSQL);
177
178 removeOldServiceComponents(buildNamespace);
179
180 return serviceComponent;
181 }
182 catch (Exception e) {
183 throw new SystemException(e);
184 }
185 }
186
187 @Override
188 public void upgradeDB(
189 final ClassLoader classLoader, final String buildNamespace,
190 final long buildNumber, final boolean buildAutoUpgrade,
191 final ServiceComponent previousServiceComponent,
192 final String tablesSQL, final String sequencesSQL,
193 final String indexesSQL)
194 throws Exception {
195
196 ProtectionDomain protectionDomain = new ProtectionDomain(
197 null, null, classLoader, null);
198
199 AccessControlContext accessControlContext = new AccessControlContext(
200 new ProtectionDomain[] {protectionDomain});
201
202 AccessController.doPrivileged(
203 new PrivilegedExceptionAction<Void>() {
204
205 @Override
206 public Void run() throws Exception {
207 doUpgradeDB(
208 classLoader, buildNamespace, buildNumber,
209 buildAutoUpgrade, previousServiceComponent, tablesSQL,
210 sequencesSQL, indexesSQL);
211
212 return null;
213 }
214
215 },
216 accessControlContext
217 );
218 }
219
220 @Override
221 public void verifyDB() throws SystemException {
222 List<ServiceComponent> serviceComponents =
223 serviceComponentPersistence.findAll();
224
225 for (ServiceComponent serviceComponent : serviceComponents) {
226 String buildNamespace = serviceComponent.getBuildNamespace();
227 String tablesSQL = serviceComponent.getTablesSQL();
228 String sequencesSQL = serviceComponent.getSequencesSQL();
229 String indexesSQL = serviceComponent.getIndexesSQL();
230
231 try {
232 serviceComponentLocalService.upgradeDB(
233 null, buildNamespace, 0, false, null, tablesSQL,
234 sequencesSQL, indexesSQL);
235 }
236 catch (Exception e) {
237 _log.error(e, e);
238 }
239 }
240 }
241
242 protected void clearCacheRegistry(ServletContext servletContext)
243 throws DocumentException {
244
245 InputStream inputStream = servletContext.getResourceAsStream(
246 "/WEB-INF/classes/META-INF/portlet-hbm.xml");
247
248 if (inputStream == null) {
249 return;
250 }
251
252 Document document = SAXReaderUtil.read(inputStream);
253
254 Element rootElement = document.getRootElement();
255
256 List<Element> classElements = rootElement.elements("class");
257
258 for (Element classElement : classElements) {
259 String name = classElement.attributeValue("name");
260
261 CacheRegistryUtil.unregister(name);
262 }
263
264 CacheRegistryUtil.clear();
265
266 EntityCacheUtil.clearCache();
267 FinderCacheUtil.clearCache();
268 }
269
270 protected void doUpgradeDB(
271 ClassLoader classLoader, String buildNamespace, long buildNumber,
272 boolean buildAutoUpgrade, ServiceComponent previousServiceComponent,
273 String tablesSQL, String sequencesSQL, String indexesSQL)
274 throws Exception {
275
276 DB db = DBFactoryUtil.getDB();
277
278 if (previousServiceComponent == null) {
279 if (_log.isInfoEnabled()) {
280 _log.info("Running " + buildNamespace + " SQL scripts");
281 }
282
283 db.runSQLTemplateString(tablesSQL, true, false);
284 db.runSQLTemplateString(sequencesSQL, true, false);
285 db.runSQLTemplateString(indexesSQL, true, false);
286 }
287 else if (buildAutoUpgrade) {
288 if (_log.isInfoEnabled()) {
289 _log.info(
290 "Upgrading " + buildNamespace +
291 " database to build number " + buildNumber);
292 }
293
294 if (!tablesSQL.equals(previousServiceComponent.getTablesSQL())) {
295 if (_log.isInfoEnabled()) {
296 _log.info("Upgrading database with tables.sql");
297 }
298
299 db.runSQLTemplateString(tablesSQL, true, false);
300
301 upgradeModels(classLoader);
302 }
303
304 if (!sequencesSQL.equals(
305 previousServiceComponent.getSequencesSQL())) {
306
307 if (_log.isInfoEnabled()) {
308 _log.info("Upgrading database with sequences.sql");
309 }
310
311 db.runSQLTemplateString(sequencesSQL, true, false);
312 }
313
314 if (!indexesSQL.equals(previousServiceComponent.getIndexesSQL())) {
315 if (_log.isInfoEnabled()) {
316 _log.info("Upgrading database with indexes.sql");
317 }
318
319 db.runSQLTemplateString(indexesSQL, true, false);
320 }
321 }
322 }
323
324 protected List<String> getModels(ClassLoader classLoader)
325 throws DocumentException, IOException {
326
327 List<String> models = new ArrayList<String>();
328
329 String xml = StringUtil.read(
330 classLoader, "META-INF/portlet-model-hints.xml");
331
332 models.addAll(getModels(xml));
333
334 try {
335 xml = StringUtil.read(
336 classLoader, "META-INF/portlet-model-hints-ext.xml");
337
338 models.addAll(getModels(xml));
339 }
340 catch (Exception e) {
341 if (_log.isInfoEnabled()) {
342 _log.info(
343 "No optional file META-INF/portlet-model-hints-ext.xml " +
344 "found");
345 }
346 }
347
348 return models;
349 }
350
351 protected List<String> getModels(String xml) throws DocumentException {
352 List<String> models = new ArrayList<String>();
353
354 Document document = SAXReaderUtil.read(xml);
355
356 Element rootElement = document.getRootElement();
357
358 List<Element> modelElements = rootElement.elements("model");
359
360 for (Element modelElement : modelElements) {
361 String name = modelElement.attributeValue("name");
362
363 models.add(name);
364 }
365
366 return models;
367 }
368
369 protected void removeOldServiceComponents(String buildNamespace)
370 throws SystemException {
371
372 int serviceComponentsCount =
373 serviceComponentPersistence.countByBuildNamespace(buildNamespace);
374
375 if (serviceComponentsCount < _MAX_SERVICE_COMPONENTS) {
376 return;
377 }
378
379 List<ServiceComponent> serviceComponents =
380 serviceComponentPersistence.findByBuildNamespace(
381 buildNamespace, _MAX_SERVICE_COMPONENTS,
382 serviceComponentsCount);
383
384 for (int i = 0; i < serviceComponents.size(); i++) {
385 ServiceComponent serviceComponent = serviceComponents.get(i);
386
387 serviceComponentPersistence.remove(serviceComponent);
388 }
389 }
390
391 protected void upgradeModels(ClassLoader classLoader) throws Exception {
392 List<String> models = getModels(classLoader);
393
394 for (String name : models) {
395 int pos = name.lastIndexOf(".model.");
396
397 name =
398 name.substring(0, pos) + ".model.impl." +
399 name.substring(pos + 7) + "ModelImpl";
400
401 Class<?> modelClass = Class.forName(name, true, classLoader);
402
403 Field tableNameField = modelClass.getField("TABLE_NAME");
404 Field tableColumnsField = modelClass.getField("TABLE_COLUMNS");
405 Field tableSQLCreateField = modelClass.getField("TABLE_SQL_CREATE");
406 Field dataSourceField = modelClass.getField("DATA_SOURCE");
407
408 String tableName = (String)tableNameField.get(null);
409 Object[][] tableColumns = (Object[][])tableColumnsField.get(null);
410 String tableSQLCreate = (String)tableSQLCreateField.get(null);
411 String dataSource = (String)dataSourceField.get(null);
412
413 if (!dataSource.equals(Entity.DEFAULT_DATA_SOURCE)) {
414 continue;
415 }
416
417 UpgradeTable upgradeTable = UpgradeTableFactoryUtil.getUpgradeTable(
418 tableName, tableColumns);
419
420 upgradeTable.setCreateSQL(tableSQLCreate);
421
422 upgradeTable.updateTable();
423 }
424 }
425
426 private static final int _MAX_SERVICE_COMPONENTS = 10;
427
428 private static Log _log = LogFactoryUtil.getLog(
429 ServiceComponentLocalServiceImpl.class);
430
431 }