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