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