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.util.HttpUtil;
29 import com.liferay.portal.kernel.util.StringPool;
30 import com.liferay.portal.kernel.util.StringUtil;
31 import com.liferay.portal.model.ModelHintsUtil;
32 import com.liferay.portal.model.ServiceComponent;
33 import com.liferay.portal.service.base.ServiceComponentLocalServiceBaseImpl;
34 import com.liferay.portal.tools.servicebuilder.Entity;
35 import com.liferay.portal.tools.sql.DBUtil;
36 import com.liferay.portal.upgrade.util.DefaultUpgradeTableImpl;
37 import com.liferay.portal.upgrade.util.UpgradeTable;
38 import com.liferay.util.xml.XMLFormatter;
39
40 import java.io.IOException;
41 import java.io.StringReader;
42
43 import java.lang.reflect.Field;
44
45 import java.util.ArrayList;
46 import java.util.Iterator;
47 import java.util.List;
48
49 import javax.servlet.ServletContext;
50
51 import org.apache.commons.logging.Log;
52 import org.apache.commons.logging.LogFactory;
53
54 import org.dom4j.Document;
55 import org.dom4j.DocumentException;
56 import org.dom4j.DocumentFactory;
57 import org.dom4j.Element;
58 import org.dom4j.io.SAXReader;
59
60
67 public class ServiceComponentLocalServiceImpl
68 extends ServiceComponentLocalServiceBaseImpl {
69
70 public ServiceComponent updateServiceComponent(
71 ServletContext servletContext, ClassLoader classLoader,
72 String buildNamespace, long buildNumber, long buildDate)
73 throws PortalException, SystemException {
74
75 try {
76 ModelHintsUtil.read(
77 classLoader, "META-INF/portlet-model-hints.xml");
78 }
79 catch (Exception e) {
80 throw new SystemException(e);
81 }
82
83 ServiceComponent serviceComponent = null;
84 ServiceComponent previousServiceComponent = null;
85
86 List<ServiceComponent> serviceComponents =
87 serviceComponentPersistence.findByBuildNamespace(
88 buildNamespace, 0, 1);
89
90 if (serviceComponents.size() == 0) {
91 long serviceComponentId = counterLocalService.increment();
92
93 serviceComponent = serviceComponentPersistence.create(
94 serviceComponentId);
95
96 serviceComponent.setBuildNamespace(buildNamespace);
97 serviceComponent.setBuildNumber(buildNumber);
98 serviceComponent.setBuildDate(buildDate);
99 }
100 else {
101 serviceComponent = serviceComponents.get(0);
102
103 if (serviceComponent.getBuildNumber() < buildNumber) {
104 previousServiceComponent = serviceComponent;
105
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 if (serviceComponent.getBuildNumber() > buildNumber) {
116 throw new OldServiceComponentException(
117 "Build namespace " + buildNamespace + " has build number " +
118 serviceComponent.getBuildNumber() +
119 " which is newer than " + buildNumber);
120 }
121 else {
122 return serviceComponent;
123 }
124 }
125
126 try {
127 DocumentFactory docFactory = DocumentFactory.getInstance();
128
129 Document doc = docFactory.createDocument(StringPool.UTF8);
130
131 Element data = doc.addElement("data");
132
133 String tablesSQL = HttpUtil.URLtoString(servletContext.getResource(
134 "/WEB-INF/sql/tables.sql"));
135
136 data.addElement("tables-sql").addCDATA(tablesSQL);
137
138 String sequencesSQL = HttpUtil.URLtoString(
139 servletContext.getResource("/WEB-INF/sql/sequences.sql"));
140
141 data.addElement("sequences-sql").addCDATA(sequencesSQL);
142
143 String indexesSQL = HttpUtil.URLtoString(servletContext.getResource(
144 "/WEB-INF/sql/indexes.sql"));
145
146 data.addElement("indexes-sql").addCDATA(indexesSQL);
147
148 String dataXML = XMLFormatter.toString(doc);
149
150 serviceComponent.setData(dataXML);
151
152 serviceComponentPersistence.update(serviceComponent, false);
153
154 upgradeDB(
155 classLoader, buildNamespace, buildNumber,
156 previousServiceComponent, tablesSQL, sequencesSQL, indexesSQL);
157
158 removeOldServiceComponents(buildNamespace);
159
160 return serviceComponent;
161 }
162 catch (Exception e) {
163 throw new SystemException(e);
164 }
165 }
166
167 protected String[] getModels(ClassLoader classLoader)
168 throws DocumentException, IOException {
169
170 List<String> models = new ArrayList<String>();
171
172 String xml = StringUtil.read(
173 classLoader, "META-INF/portlet-model-hints.xml");
174
175 SAXReader reader = new SAXReader();
176
177 Document doc = reader.read(new StringReader(xml));
178
179 Element root = doc.getRootElement();
180
181 Iterator<Element> itr = root.elements("model").iterator();
182
183 while (itr.hasNext()) {
184 Element modelEl = itr.next();
185
186 String name = modelEl.attributeValue("name");
187
188 models.add(name);
189 }
190
191 return models.toArray(new String[models.size()]);
192 }
193
194 protected void upgradeDB(
195 ClassLoader classLoader, String buildNamespace, long buildNumber,
196 ServiceComponent previousServiceComponent, String tablesSQL,
197 String sequencesSQL, String indexesSQL)
198 throws Exception {
199
200 DBUtil dbUtil = DBUtil.getInstance();
201
202 if (previousServiceComponent == null) {
203 if (_log.isInfoEnabled()) {
204 _log.info(
205 "Running " + buildNamespace +
206 " SQL scripts for the first time");
207 }
208
209 dbUtil.runSQLTemplateString(tablesSQL, true, false);
210 dbUtil.runSQLTemplateString(sequencesSQL, true, false);
211 dbUtil.runSQLTemplateString(indexesSQL, true, false);
212 }
213 else {
214 if (_log.isInfoEnabled()) {
215 _log.info(
216 "Upgrading " + buildNamespace +
217 " database to build number " + buildNumber);
218 }
219
220 if (!tablesSQL.equals(
221 previousServiceComponent.getTablesSQL())) {
222
223 if (_log.isInfoEnabled()) {
224 _log.info("Upgrading database with tables.sql");
225 }
226
227 dbUtil.runSQLTemplateString(tablesSQL, true, false);
228
229 upgradeModels(classLoader);
230 }
231
232 if (!sequencesSQL.equals(
233 previousServiceComponent.getSequencesSQL())) {
234
235 if (_log.isInfoEnabled()) {
236 _log.info("Upgrading database with sequences.sql");
237 }
238
239 dbUtil.runSQLTemplateString(sequencesSQL, true, false);
240 }
241
242 if (!indexesSQL.equals(
243 previousServiceComponent.getIndexesSQL())) {
244
245 if (_log.isInfoEnabled()) {
246 _log.info("Upgrading database with indexes.sql");
247 }
248
249 dbUtil.runSQLTemplateString(indexesSQL, true, false);
250 }
251 }
252 }
253
254 protected void upgradeModels(ClassLoader classLoader) throws Exception {
255 String[] models = getModels(classLoader);
256
257 for (int i = 0; i < models.length; i++) {
258 String name = models[i];
259
260 int pos = name.lastIndexOf(".model.");
261
262 name =
263 name.substring(0, pos) + ".model.impl." +
264 name.substring(pos + 7) + "ModelImpl";
265
266 Class<?> modelClass = Class.forName(name, true, classLoader);
267
268 Field tableNameField = modelClass.getField("TABLE_NAME");
269 Field tableColumnsField = modelClass.getField("TABLE_COLUMNS");
270 Field tableSQLCreateField = modelClass.getField("TABLE_SQL_CREATE");
271 Field dataSourceField = modelClass.getField("DATA_SOURCE");
272
273 String tableName = (String)tableNameField.get(null);
274 Object[][] tableColumns = (Object[][])tableColumnsField.get(null);
275 String tableSQLCreate = (String)tableSQLCreateField.get(null);
276 String dataSource = (String)dataSourceField.get(null);
277
278 if (!dataSource.equals(Entity.DEFAULT_DATA_SOURCE)) {
279 continue;
280 }
281
282 UpgradeTable upgradeTable = new DefaultUpgradeTableImpl(
283 tableName, tableColumns);
284
285 upgradeTable.setCreateSQL(tableSQLCreate);
286
287 upgradeTable.updateTable();
288 }
289 }
290
291 protected void removeOldServiceComponents(String buildNamespace)
292 throws SystemException {
293
294 int serviceComponentsCount =
295 serviceComponentPersistence.countByBuildNamespace(buildNamespace);
296
297 if (serviceComponentsCount < _MAX_SERVICE_COMPONENTS) {
298 return;
299 }
300
301 List<ServiceComponent> serviceComponents =
302 serviceComponentPersistence.findByBuildNamespace(
303 buildNamespace, _MAX_SERVICE_COMPONENTS,
304 serviceComponentsCount);
305
306 for (int i = 0; i < serviceComponents.size(); i++) {
307 ServiceComponent serviceComponent = serviceComponents.get(i);
308
309 serviceComponentPersistence.remove(serviceComponent);
310 }
311 }
312
313 private static final int _MAX_SERVICE_COMPONENTS = 10;
314
315 private static Log _log =
316 LogFactory.getLog(ServiceComponentLocalServiceImpl.class);
317
318 }