001
014
015 package com.liferay.portal.upgrade.v6_1_0;
016
017 import com.liferay.portal.image.DLHook;
018 import com.liferay.portal.image.DatabaseHook;
019 import com.liferay.portal.image.FileSystemHook;
020 import com.liferay.portal.kernel.dao.jdbc.DataAccess;
021 import com.liferay.portal.kernel.image.Hook;
022 import com.liferay.portal.kernel.log.Log;
023 import com.liferay.portal.kernel.log.LogFactoryUtil;
024 import com.liferay.portal.kernel.upgrade.UpgradeProcess;
025 import com.liferay.portal.kernel.util.FileUtil;
026 import com.liferay.portal.kernel.util.MimeTypesUtil;
027 import com.liferay.portal.kernel.util.StringBundler;
028 import com.liferay.portal.kernel.util.StringPool;
029 import com.liferay.portal.kernel.util.Validator;
030 import com.liferay.portal.model.Image;
031 import com.liferay.portal.security.pacl.PACLClassLoaderUtil;
032 import com.liferay.portal.service.ImageLocalServiceUtil;
033 import com.liferay.portal.util.PropsValues;
034 import com.liferay.portlet.documentlibrary.model.DLFileEntry;
035 import com.liferay.portlet.documentlibrary.model.DLFolder;
036 import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
037 import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
038 import com.liferay.portlet.documentlibrary.util.ImageProcessorUtil;
039
040 import java.io.InputStream;
041
042 import java.sql.Connection;
043 import java.sql.DatabaseMetaData;
044 import java.sql.PreparedStatement;
045 import java.sql.ResultSet;
046 import java.sql.Timestamp;
047
048 import java.util.HashMap;
049 import java.util.Map;
050
051
055 public class UpgradeImageGallery extends UpgradeProcess {
056
057 public UpgradeImageGallery() throws Exception {
058 ClassLoader classLoader = PACLClassLoaderUtil.getPortalClassLoader();
059
060 _sourceHookClassName = FileSystemHook.class.getName();
061
062 if (Validator.isNotNull(PropsValues.IMAGE_HOOK_IMPL)) {
063 _sourceHookClassName = PropsValues.IMAGE_HOOK_IMPL;
064 }
065
066 _sourceHook = (Hook)classLoader.loadClass(
067 _sourceHookClassName).newInstance();
068 }
069
070 protected void addDLFileEntry(
071 String uuid, long fileEntryId, long groupId, long companyId,
072 long userId, String userName, long versionUserId,
073 String versionUserName, Timestamp createDate,
074 Timestamp modifiedDate, long repositoryId, long folderId,
075 String name, String extension, String mimeType, String title,
076 String description, String extraSettings, String version, long size,
077 int readCount, long smallImageId, long largeImageId,
078 long custom1ImageId, long custom2ImageId)
079 throws Exception {
080
081 Connection con = null;
082 PreparedStatement ps = null;
083
084 try {
085 con = DataAccess.getUpgradeOptimizedConnection();
086
087 StringBundler sb = new StringBundler(9);
088
089 sb.append("insert into DLFileEntry (uuid_, fileEntryId, groupId, ");
090 sb.append("companyId, userId, userName, versionUserId, ");
091 sb.append("versionUserName, createDate, modifiedDate, ");
092 sb.append("repositoryId, folderId, name, extension, mimeType, ");
093 sb.append("title, description, extraSettings, version, size_, ");
094 sb.append("readCount, smallImageId, largeImageId, ");
095 sb.append("custom1ImageId, custom2ImageId) values (");
096 sb.append("?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ");
097 sb.append("?, ?, ?, ?, ?, ?, ?, ?)");
098
099 String sql = sb.toString();
100
101 ps = con.prepareStatement(sql);
102
103 ps.setString(1, uuid);
104 ps.setLong(2, fileEntryId);
105 ps.setLong(3, groupId);
106 ps.setLong(4, companyId);
107 ps.setLong(5, userId);
108 ps.setString(6, userName);
109 ps.setLong(7, versionUserId);
110 ps.setString(8, versionUserName);
111 ps.setTimestamp(9, createDate);
112 ps.setTimestamp(10, modifiedDate);
113 ps.setLong(11, repositoryId);
114 ps.setLong(12, folderId);
115 ps.setString(13, name);
116 ps.setString(14, extension);
117 ps.setString(15, mimeType);
118 ps.setString(16, title);
119 ps.setString(17, description);
120 ps.setString(18, extraSettings);
121 ps.setString(19, version);
122 ps.setLong(20, size);
123 ps.setInt(21, readCount);
124 ps.setLong(22, smallImageId);
125 ps.setLong(23, largeImageId);
126 ps.setLong(24, custom1ImageId);
127 ps.setLong(25, custom2ImageId);
128
129 ps.executeUpdate();
130 }
131 finally {
132 DataAccess.cleanUp(con, ps);
133 }
134 }
135
136 protected void addDLFileVersion(
137 long fileVersionId, long groupId, long companyId, long userId,
138 String userName, Timestamp createDate, long repositoryId,
139 long folderId, long fileEntryId, String extension, String mimeType,
140 String title, String description, String changeLog,
141 String extraSettings, long fileEntryTypeId, String version,
142 long size, int status, long statusByUserId, String statusByUserName,
143 Timestamp statusDate)
144 throws Exception {
145
146 Connection con = null;
147 PreparedStatement ps = null;
148
149 try {
150 con = DataAccess.getUpgradeOptimizedConnection();
151
152 StringBundler sb = new StringBundler(9);
153
154 sb.append("insert into DLFileVersion (fileVersionId, groupId, ");
155 sb.append("companyId, userId, userName, createDate, ");
156 sb.append("modifiedDate, repositoryId, folderId, fileEntryId, ");
157 sb.append("extension, mimeType, title, description, changeLog, ");
158 sb.append("extraSettings, fileEntryTypeId, version, size_, ");
159 sb.append("status, statusByUserId, statusByUserName, statusDate) ");
160 sb.append("values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ");
161 sb.append("?, ?, ?, ?, ?, ?, ?, ?)");
162
163 String sql = sb.toString();
164
165 ps = con.prepareStatement(sql);
166
167 ps.setLong(1, fileVersionId);
168 ps.setLong(2, groupId);
169 ps.setLong(3, companyId);
170 ps.setLong(4, userId);
171 ps.setString(5, userName);
172 ps.setTimestamp(6, createDate);
173 ps.setTimestamp(7, statusDate);
174 ps.setLong(8, repositoryId);
175 ps.setLong(9, folderId);
176 ps.setLong(10, fileEntryId);
177 ps.setString(11, extension);
178 ps.setString(12, mimeType);
179 ps.setString(13, title);
180 ps.setString(14, description);
181 ps.setString(15, changeLog);
182 ps.setString(16, extraSettings);
183 ps.setLong(17, fileEntryTypeId);
184 ps.setString(18, version);
185 ps.setLong(19, size);
186 ps.setInt(20, status);
187 ps.setLong(21, statusByUserId);
188 ps.setString(22, statusByUserName);
189 ps.setTimestamp(23, statusDate);
190
191 ps.executeUpdate();
192 }
193 finally {
194 DataAccess.cleanUp(con, ps);
195 }
196 }
197
198 protected void addDLFolderEntry(
199 String uuid, long folderId, long groupId, long companyId,
200 long userId, String userName, Timestamp createDate,
201 Timestamp modifiedDate, long repositoryId, long parentFolderId,
202 String name, String description, Timestamp lastPostDate)
203 throws Exception {
204
205 Connection con = null;
206 PreparedStatement ps = null;
207
208 try {
209 con = DataAccess.getUpgradeOptimizedConnection();
210
211 StringBundler sb = new StringBundler(5);
212
213 sb.append("insert into DLFolder (uuid_, folderId, groupId, ");
214 sb.append("companyId, userId, userName, createDate, ");
215 sb.append("modifiedDate, repositoryId, mountPoint, ");
216 sb.append("parentFolderId, name, description, lastPostDate) ");
217 sb.append("values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
218
219 String sql = sb.toString();
220
221 ps = con.prepareStatement(sql);
222
223 ps.setString(1, uuid);
224 ps.setLong(2, folderId);
225 ps.setLong(3, groupId);
226 ps.setLong(4, companyId);
227 ps.setLong(5, userId);
228 ps.setString(6, userName);
229 ps.setTimestamp(7, createDate);
230 ps.setTimestamp(8, modifiedDate);
231 ps.setLong(9, repositoryId);
232 ps.setBoolean(10, false);
233 ps.setLong(11, parentFolderId);
234 ps.setString(12, name);
235 ps.setString(13, description);
236 ps.setTimestamp(14, lastPostDate);
237
238 ps.executeUpdate();
239 }
240 finally {
241 DataAccess.cleanUp(con, ps);
242 }
243 }
244
245 protected void deleteConflictingIGPermissions(
246 String igResourceName, String dlResourceName)
247 throws Exception {
248
249 Connection con = null;
250 PreparedStatement ps = null;
251 ResultSet rs = null;
252
253 try {
254 con = DataAccess.getUpgradeOptimizedConnection();
255
256 DatabaseMetaData databaseMetaData = con.getMetaData();
257
258 boolean supportsBatchUpdates =
259 databaseMetaData.supportsBatchUpdates();
260
261 ps = con.prepareStatement(
262 "select companyId, scope, primKey, roleId from " +
263 "ResourcePermission where name = ?");
264
265 ps.setString(1, igResourceName);
266
267 rs = ps.executeQuery();
268
269 ps = con.prepareStatement(
270 "delete from ResourcePermission where name = ? and " +
271 "companyId = ? and scope = ? and primKey = ? and " +
272 "roleId = ?");
273
274 int count = 0;
275
276 while (rs.next()) {
277 ps.setString(1, dlResourceName);
278 ps.setLong(2, rs.getLong("companyId"));
279 ps.setInt(3, rs.getInt("scope"));
280 ps.setString(4, rs.getString("primKey"));
281 ps.setLong(5, rs.getLong("roleId"));
282
283 if (supportsBatchUpdates) {
284 ps.addBatch();
285
286 if (count == PropsValues.HIBERNATE_JDBC_BATCH_SIZE) {
287 ps.executeBatch();
288
289 count = 0;
290 }
291 else {
292 count++;
293 }
294 }
295 else {
296 ps.executeUpdate();
297 }
298 }
299
300 if (supportsBatchUpdates && (count > 0)) {
301 ps.executeBatch();
302 }
303 }
304 finally {
305 DataAccess.cleanUp(con, ps, rs);
306 }
307 }
308
309 @Override
310 protected void doUpgrade() throws Exception {
311 updateIGFolderEntries();
312 updateIGImageEntries();
313 updateIGFolderPermissions();
314 updateIGImagePermissions();
315
316 migrateImageFiles();
317
318 UpgradeDocumentLibrary upgradeDocumentLibrary =
319 new UpgradeDocumentLibrary();
320
321 upgradeDocumentLibrary.updateSyncs();
322 }
323
324 protected Object[] getImage(long imageId) throws Exception {
325 Connection con = null;
326 PreparedStatement ps = null;
327 ResultSet rs = null;
328
329 try {
330 con = DataAccess.getUpgradeOptimizedConnection();
331
332 ps = con.prepareStatement(
333 "select type_, size_ from Image where imageId = " + imageId);
334
335 rs = ps.executeQuery();
336
337 if (rs.next()) {
338 String type = rs.getString("type_");
339 long size = rs.getInt("size_");
340
341 return new Object[] {type, size};
342 }
343
344 return null;
345 }
346 finally {
347 DataAccess.cleanUp(con, ps, rs);
348 }
349 }
350
351 protected void migrateFile(
352 long repositoryId, long companyId, String name, Image image)
353 throws Exception {
354
355 InputStream is = _sourceHook.getImageAsStream(image);
356
357 byte[] bytes = FileUtil.getBytes(is);
358
359 if (name == null) {
360 name = image.getImageId() + StringPool.PERIOD + image.getType();
361 }
362
363 if (DLStoreUtil.hasFile(companyId, repositoryId, name)) {
364 DLStoreUtil.deleteFile(companyId, repositoryId, name);
365 }
366
367 DLStoreUtil.addFile(companyId, repositoryId, name, false, bytes);
368 }
369
370 protected void migrateImage(long imageId) throws Exception {
371 Image image = ImageLocalServiceUtil.getImage(imageId);
372
373 try {
374 migrateFile(0, 0, null, image);
375 }
376 catch (Exception e) {
377 if (_log.isWarnEnabled()) {
378 _log.warn("Ignoring exception for image " + imageId, e);
379 }
380
381 return;
382 }
383
384 _sourceHook.deleteImage(image);
385 }
386
387 protected void migrateImage(
388 long fileEntryId, long companyId, long groupId, long folderId,
389 String name, long smallImageId, long largeImageId,
390 long custom1ImageId, long custom2ImageId)
391 throws Exception {
392
393 Image largeImage = null;
394
395 if (largeImageId != 0) {
396 largeImage = ImageLocalServiceUtil.getImage(largeImageId);
397
398 long repositoryId = DLFolderConstants.getDataRepositoryId(
399 groupId, folderId);
400
401 try {
402 migrateFile(repositoryId, companyId, name, largeImage);
403 }
404 catch (Exception e) {
405 if (_log.isWarnEnabled()) {
406 _log.warn(
407 "Ignoring exception for image " + largeImageId, e);
408 }
409 }
410 }
411
412 long thumbnailImageId = 0;
413
414 if (smallImageId != 0) {
415 thumbnailImageId = smallImageId;
416 }
417 else if (custom1ImageId != 0) {
418 thumbnailImageId = custom1ImageId;
419 }
420 else if (custom2ImageId != 0) {
421 thumbnailImageId = custom2ImageId;
422 }
423
424 Image thumbnailImage = null;
425
426 if (thumbnailImageId != 0) {
427 thumbnailImage = ImageLocalServiceUtil.getImage(thumbnailImageId);
428
429 Connection con = null;
430 PreparedStatement ps = null;
431 ResultSet rs = null;
432
433 try {
434 InputStream is = _sourceHook.getImageAsStream(thumbnailImage);
435
436 con = DataAccess.getUpgradeOptimizedConnection();
437
438 ps = con.prepareStatement(
439 "select max(fileVersionId) from DLFileVersion where " +
440 "fileEntryId = " + fileEntryId);
441
442 rs = ps.executeQuery();
443
444 if (rs.next()) {
445 long fileVersionId = rs.getLong(1);
446
447 ImageProcessorUtil.storeThumbnail(
448 companyId, groupId, fileEntryId, fileVersionId,
449 custom1ImageId, custom2ImageId, is,
450 thumbnailImage.getType());
451 }
452 }
453 catch (Exception e) {
454 if (_log.isWarnEnabled()) {
455 _log.warn(
456 "Ignoring exception for image " + thumbnailImageId, e);
457 }
458 }
459 finally {
460 DataAccess.cleanUp(con, ps, rs);
461 }
462 }
463
464 if (largeImageId != 0) {
465 _sourceHook.deleteImage(largeImage);
466
467 runSQL("delete from Image where imageId = " + largeImageId);
468 }
469
470 if ((largeImageId != thumbnailImageId) && (thumbnailImageId != 0)) {
471 _sourceHook.deleteImage(thumbnailImage);
472
473 runSQL("delete from Image where imageId = " + thumbnailImageId);
474 }
475 }
476
477 protected void migrateImageFiles() throws Exception {
478 Connection con = null;
479 PreparedStatement ps = null;
480 ResultSet rs = null;
481
482 try {
483 con = DataAccess.getUpgradeOptimizedConnection();
484
485 StringBundler sb = new StringBundler(8);
486
487 sb.append("select fileEntryId, companyId, groupId, folderId, ");
488 sb.append("name, smallImageId, largeImageId, custom1ImageId, ");
489 sb.append("custom2ImageId from DLFileEntry where ((smallImageId ");
490 sb.append("is not null) and (smallImageId != 0)) or ");
491 sb.append("((largeImageId is not null) and (largeImageId != 0)) ");
492 sb.append("or ((custom1ImageId is not null) and (custom1ImageId ");
493 sb.append("!= 0)) or ((custom2ImageId is not null) and ");
494 sb.append("(custom2ImageId != 0))");
495
496 ps = con.prepareStatement(sb.toString());
497
498 rs = ps.executeQuery();
499
500 while (rs.next()) {
501 long fileEntryId = rs.getLong("fileEntryId");
502 long companyId = rs.getLong("companyId");
503 long groupId = rs.getLong("groupId");
504 long folderId = rs.getLong("folderId");
505 String name = rs.getString("name");
506 long smallImageId = rs.getLong("smallImageId");
507 long largeImageId = rs.getLong("largeImageId");
508 long custom1ImageId = rs.getLong("custom1ImageId");
509 long custom2ImageId = rs.getLong("custom2ImageId");
510
511 migrateImage(
512 fileEntryId, companyId, groupId, folderId, name,
513 smallImageId, largeImageId, custom1ImageId, custom2ImageId);
514 }
515 }
516 finally {
517 DataAccess.cleanUp(con, ps, rs);
518 }
519
520 if (!_sourceHookClassName.equals(DLHook.class.getName())) {
521 try {
522 con = DataAccess.getUpgradeOptimizedConnection();
523
524 ps = con.prepareStatement("select imageId from Image");
525
526 rs = ps.executeQuery();
527
528 while (rs.next()) {
529 long imageId = rs.getLong("imageId");
530
531 migrateImage(imageId);
532 }
533 }
534 finally {
535 DataAccess.cleanUp(con, ps, rs);
536 }
537
538 if (_sourceHookClassName.equals(DatabaseHook.class.getName())) {
539 runSQL("update Image set text_ = ''");
540 }
541 }
542 }
543
544 protected void updateIGFolderEntries() throws Exception {
545 Connection con = null;
546 PreparedStatement ps = null;
547 ResultSet rs = null;
548
549 try {
550 con = DataAccess.getUpgradeOptimizedConnection();
551
552 ps = con.prepareStatement(
553 "select * from IGFolder order by folderId asc");
554
555 rs = ps.executeQuery();
556
557 Map<Long, Long> folderIds = new HashMap<Long, Long>();
558
559 while (rs.next()) {
560 String uuid = rs.getString("uuid_");
561 long folderId = rs.getLong("folderId");
562 long groupId = rs.getLong("groupId");
563 long companyId = rs.getLong("companyId");
564 long userId = rs.getLong("userId");
565 String userName = rs.getString("userName");
566 Timestamp createDate = rs.getTimestamp("createDate");
567 Timestamp modifiedDate = rs.getTimestamp("modifiedDate");
568 long parentFolderId = rs.getLong("parentFolderId");
569 String name = rs.getString("name");
570 String description = rs.getString("description");
571
572 if (folderIds.containsKey(parentFolderId)) {
573 parentFolderId = folderIds.get(parentFolderId);
574 }
575
576 boolean update = updateIGImageFolderId(
577 groupId, name, parentFolderId, folderId, folderIds);
578
579 if (!update) {
580 addDLFolderEntry(
581 uuid, folderId, groupId, companyId, userId, userName,
582 createDate, modifiedDate, groupId, parentFolderId, name,
583 description, modifiedDate);
584 }
585 }
586
587 runSQL("drop table IGFolder");
588 }
589 finally {
590 DataAccess.cleanUp(con, ps, rs);
591 }
592 }
593
594 protected void updateIGFolderPermissions() throws Exception {
595 if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM != 6) {
596 return;
597 }
598
599 deleteConflictingIGPermissions(
600 _IG_FOLDER_CLASS_NAME, DLFolder.class.getName());
601
602 runSQL("update ResourcePermission set name = '" +
603 DLFolder.class.getName() +
604 "' where name = '" + _IG_FOLDER_CLASS_NAME + "'");
605 }
606
607 protected void updateIGImageEntries() throws Exception {
608 Connection con = null;
609 PreparedStatement ps = null;
610 ResultSet rs = null;
611
612 try {
613 con = DataAccess.getUpgradeOptimizedConnection();
614
615 ps = con.prepareStatement("select * from IGImage");
616
617 rs = ps.executeQuery();
618
619 while (rs.next()) {
620 String uuid = rs.getString("uuid_");
621 long imageId = rs.getLong("imageId");
622 long groupId = rs.getLong("groupId");
623 long companyId = rs.getLong("companyId");
624 long userId = rs.getLong("userId");
625 String userName = rs.getString("userName");
626 Timestamp createDate = rs.getTimestamp("createDate");
627 Timestamp modifiedDate = rs.getTimestamp("modifiedDate");
628 long folderId = rs.getLong("folderId");
629 String title = rs.getString("name");
630 String description = rs.getString("description");
631 long smallImageId = rs.getLong("smallImageId");
632 long largeImageId = rs.getLong("largeImageId");
633 long custom1ImageId = rs.getLong("custom1ImageId");
634 long custom2ImageId = rs.getLong("custom2ImageId");
635
636 Object[] image = getImage(largeImageId);
637
638 if (image == null) {
639 continue;
640 }
641
642 String extension = (String)image[0];
643
644 String mimeType = MimeTypesUtil.getContentType(
645 "A." + extension);
646
647 String name = String.valueOf(
648 increment(DLFileEntry.class.getName()));
649
650 long size = (Long)image[1];
651
652 try {
653 addDLFileEntry(
654 uuid, imageId, groupId, companyId, userId, userName,
655 userId, userName, createDate, modifiedDate, groupId,
656 folderId, name, extension, mimeType, title, description,
657 StringPool.BLANK, "1.0", size, 0, smallImageId,
658 largeImageId, custom1ImageId, custom2ImageId);
659 }
660 catch (Exception e) {
661 title = title.concat(StringPool.SPACE).concat(
662 String.valueOf(imageId));
663
664 addDLFileEntry(
665 uuid, imageId, groupId, companyId, userId, userName,
666 userId, userName, createDate, modifiedDate, groupId,
667 folderId, name, extension, mimeType, title, description,
668 StringPool.BLANK, "1.0", size, 0, smallImageId,
669 largeImageId, custom1ImageId, custom2ImageId);
670 }
671
672 addDLFileVersion(
673 increment(), groupId, companyId, userId, userName,
674 createDate, groupId, folderId, imageId, extension, mimeType,
675 title, description, StringPool.BLANK, StringPool.BLANK, 0,
676 "1.0", size, 0, userId, userName, modifiedDate);
677 }
678
679 runSQL("drop table IGImage");
680 }
681 finally {
682 DataAccess.cleanUp(con, ps, rs);
683 }
684 }
685
686 protected boolean updateIGImageFolderId(
687 long groupId, String name, long parentFolderId, long folderId,
688 Map<Long, Long> folderIds)
689 throws Exception {
690
691 Connection con = null;
692 PreparedStatement ps = null;
693 ResultSet rs = null;
694
695 try {
696 con = DataAccess.getUpgradeOptimizedConnection();
697
698 ps = con.prepareStatement(
699 "select folderId from DLFolder where groupId = " + groupId +
700 " and parentFolderId = " + parentFolderId +
701 " and name = ?");
702
703 ps.setString(1, name);
704
705 rs = ps.executeQuery();
706
707 if (rs.next()) {
708 long newFolderId = rs.getLong("folderId");
709
710 runSQL(
711 "update IGImage set folderId = " + newFolderId +
712 " where folderId = " + folderId);
713
714 folderIds.put(folderId, newFolderId);
715
716 return true;
717 }
718 }
719 finally {
720 DataAccess.cleanUp(con, ps, rs);
721 }
722
723 return false;
724 }
725
726 protected void updateIGImagePermissions() throws Exception {
727 if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM != 6) {
728 return;
729 }
730
731 deleteConflictingIGPermissions(
732 _IG_IMAGE_CLASS_NAME, DLFileEntry.class.getName());
733
734 runSQL(
735 "update ResourcePermission set name = '" +
736 DLFileEntry.class.getName() + "' where name = '" +
737 _IG_IMAGE_CLASS_NAME + "'");
738 }
739
740 private static final String _IG_FOLDER_CLASS_NAME =
741 "com.liferay.portlet.imagegallery.model.IGFolder";
742
743 private static final String _IG_IMAGE_CLASS_NAME =
744 "com.liferay.portlet.imagegallery.model.IGImage";
745
746 private static Log _log = LogFactoryUtil.getLog(UpgradeImageGallery.class);
747
748 private Hook _sourceHook;
749 private String _sourceHookClassName;
750
751 }