1
22
23 package com.liferay.portlet.communities.action;
24
25 import com.germinus.easyconf.Filter;
26
27 import com.liferay.portal.LayoutFriendlyURLException;
28 import com.liferay.portal.LayoutHiddenException;
29 import com.liferay.portal.LayoutNameException;
30 import com.liferay.portal.LayoutParentLayoutIdException;
31 import com.liferay.portal.LayoutSetVirtualHostException;
32 import com.liferay.portal.LayoutTypeException;
33 import com.liferay.portal.NoSuchGroupException;
34 import com.liferay.portal.NoSuchLayoutException;
35 import com.liferay.portal.RequiredLayoutException;
36 import com.liferay.portal.events.EventsProcessor;
37 import com.liferay.portal.kernel.language.LanguageUtil;
38 import com.liferay.portal.kernel.util.Constants;
39 import com.liferay.portal.kernel.util.LocaleUtil;
40 import com.liferay.portal.kernel.util.ParamUtil;
41 import com.liferay.portal.kernel.util.SafeProperties;
42 import com.liferay.portal.kernel.util.StringMaker;
43 import com.liferay.portal.kernel.util.StringUtil;
44 import com.liferay.portal.kernel.util.Validator;
45 import com.liferay.portal.model.ColorScheme;
46 import com.liferay.portal.model.Group;
47 import com.liferay.portal.model.Layout;
48 import com.liferay.portal.model.LayoutTypePortlet;
49 import com.liferay.portal.model.PortletPreferencesIds;
50 import com.liferay.portal.model.User;
51 import com.liferay.portal.model.impl.LayoutImpl;
52 import com.liferay.portal.security.auth.PrincipalException;
53 import com.liferay.portal.security.permission.ActionKeys;
54 import com.liferay.portal.security.permission.PermissionChecker;
55 import com.liferay.portal.service.GroupLocalServiceUtil;
56 import com.liferay.portal.service.GroupServiceUtil;
57 import com.liferay.portal.service.LayoutLocalServiceUtil;
58 import com.liferay.portal.service.LayoutServiceUtil;
59 import com.liferay.portal.service.LayoutSetServiceUtil;
60 import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
61 import com.liferay.portal.service.UserLocalServiceUtil;
62 import com.liferay.portal.service.impl.ThemeLocalUtil;
63 import com.liferay.portal.service.permission.GroupPermissionUtil;
64 import com.liferay.portal.service.permission.OrganizationPermissionUtil;
65 import com.liferay.portal.service.permission.UserPermissionUtil;
66 import com.liferay.portal.struts.PortletAction;
67 import com.liferay.portal.theme.ThemeDisplay;
68 import com.liferay.portal.util.PortalUtil;
69 import com.liferay.portal.util.PortletKeys;
70 import com.liferay.portal.util.PropsUtil;
71 import com.liferay.portal.util.PropsValues;
72 import com.liferay.portal.util.UploadRequestUtil;
73 import com.liferay.portal.util.WebKeys;
74 import com.liferay.portlet.ActionResponseImpl;
75 import com.liferay.portlet.PortletPreferencesFactoryUtil;
76 import com.liferay.portlet.communities.util.CommunitiesUtil;
77 import com.liferay.portlet.communities.util.StagingUtil;
78 import com.liferay.portlet.tasks.NoSuchProposalException;
79 import com.liferay.util.FileUtil;
80 import com.liferay.util.servlet.SessionErrors;
81 import com.liferay.util.servlet.UploadException;
82 import com.liferay.util.servlet.UploadPortletRequest;
83
84 import java.io.File;
85
86 import java.util.HashMap;
87 import java.util.List;
88 import java.util.Locale;
89 import java.util.Map;
90 import java.util.Properties;
91
92 import javax.portlet.ActionRequest;
93 import javax.portlet.ActionResponse;
94 import javax.portlet.PortletConfig;
95 import javax.portlet.PortletPreferences;
96 import javax.portlet.PortletRequest;
97 import javax.portlet.RenderRequest;
98 import javax.portlet.RenderResponse;
99
100 import javax.servlet.http.HttpServletRequest;
101 import javax.servlet.http.HttpServletResponse;
102
103 import org.apache.struts.action.ActionForm;
104 import org.apache.struts.action.ActionForward;
105 import org.apache.struts.action.ActionMapping;
106
107
113 public class EditPagesAction extends PortletAction {
114
115 public void processAction(
116 ActionMapping mapping, ActionForm form, PortletConfig config,
117 ActionRequest req, ActionResponse res)
118 throws Exception {
119
120 try {
121 checkPermissions(req);
122 }
123 catch (PrincipalException pe) {
124 return;
125 }
126
127 String cmd = ParamUtil.getString(req, Constants.CMD);
128
129 try {
130 if (cmd.equals(Constants.ADD) || cmd.equals(Constants.UPDATE)) {
131 updateLayout(req, res);
132 }
133 else if (cmd.equals(Constants.DELETE)) {
134 CommunitiesUtil.deleteLayout(req, res);
135 }
136 else if (cmd.equals("copy_from_live")) {
137 StagingUtil.copyFromLive(req);
138 }
139 else if (cmd.equals("display_order")) {
140 updateDisplayOrder(req);
141 }
142 else if (cmd.equals("logo")) {
143 updateLogo(req);
144 }
145 else if (cmd.equals("look_and_feel")) {
146 updateLookAndFeel(req);
147 }
148 else if (cmd.equals("merge_pages")) {
149 updateMergePages(req);
150 }
151 else if (cmd.equals("monitoring")) {
152 updateMonitoring(req);
153 }
154 else if (cmd.equals("publish_to_live")) {
155 StagingUtil.publishToLive(req);
156 }
157 else if (cmd.equals("staging")) {
158 StagingUtil.updateStaging(req);
159 }
160 else if (cmd.equals("virtual_host")) {
161 updateVirtualHost(req);
162 }
163 else if (cmd.equals("workflow")) {
164 updateWorkflow(req);
165 }
166
167 String redirect = ParamUtil.getString(req, "pagesRedirect");
168
169 sendRedirect(req, res, redirect);
170 }
171 catch (Exception e) {
172 if (e instanceof NoSuchLayoutException ||
173 e instanceof NoSuchProposalException ||
174 e instanceof PrincipalException) {
175
176 SessionErrors.add(req, e.getClass().getName());
177
178 setForward(req, "portlet.communities.error");
179 }
180 else if (e instanceof LayoutFriendlyURLException ||
181 e instanceof LayoutHiddenException ||
182 e instanceof LayoutNameException ||
183 e instanceof LayoutParentLayoutIdException ||
184 e instanceof LayoutSetVirtualHostException ||
185 e instanceof LayoutTypeException ||
186 e instanceof RequiredLayoutException ||
187 e instanceof UploadException) {
188
189 if (e instanceof LayoutFriendlyURLException) {
190 SessionErrors.add(
191 req, LayoutFriendlyURLException.class.getName(), e);
192 }
193 else {
194 SessionErrors.add(req, e.getClass().getName(), e);
195 }
196 }
197 else {
198 throw e;
199 }
200 }
201 }
202
203 public ActionForward render(
204 ActionMapping mapping, ActionForm form, PortletConfig config,
205 RenderRequest req, RenderResponse res)
206 throws Exception {
207
208 try {
209 checkPermissions(req);
210 }
211 catch (PrincipalException pe) {
212 SessionErrors.add(req, PrincipalException.class.getName());
213
214 return mapping.findForward("portlet.communities.error");
215 }
216
217 try {
218 ActionUtil.getGroup(req);
219 }
220 catch (Exception e) {
221 if (e instanceof NoSuchGroupException ||
222 e instanceof PrincipalException) {
223
224 SessionErrors.add(req, e.getClass().getName());
225
226 return mapping.findForward("portlet.communities.error");
227 }
228 else {
229 throw e;
230 }
231 }
232
233 return mapping.findForward(
234 getForward(req, "portlet.communities.edit_pages"));
235 }
236
237 protected void checkPermissions(PortletRequest req) throws Exception {
238
239
241 ThemeDisplay themeDisplay = (ThemeDisplay)req.getAttribute(
242 WebKeys.THEME_DISPLAY);
243
244 PermissionChecker permissionChecker =
245 themeDisplay.getPermissionChecker();
246
247 long groupId = ParamUtil.getLong(req, "groupId");
248
249 Group group = GroupLocalServiceUtil.getGroup(groupId);
250
251 if (group.isCommunity()) {
252 if (!GroupPermissionUtil.contains(
253 permissionChecker, group.getGroupId(),
254 ActionKeys.APPROVE_PROPOSAL) &&
255 !GroupPermissionUtil.contains(
256 permissionChecker, group.getGroupId(),
257 ActionKeys.MANAGE_LAYOUTS)) {
258
259 throw new PrincipalException();
260 }
261 }
262 else if (group.isOrganization()) {
263 long organizationId = group.getClassPK();
264
265 if (!OrganizationPermissionUtil.contains(
266 permissionChecker, organizationId,
267 ActionKeys.APPROVE_PROPOSAL) &&
268 !OrganizationPermissionUtil.contains(
269 permissionChecker, organizationId,
270 ActionKeys.MANAGE_LAYOUTS)) {
271
272 throw new PrincipalException();
273 }
274 }
275 else if (group.isUser()) {
276 long groupUserId = group.getClassPK();
277
278 User groupUser = UserLocalServiceUtil.getUserById(groupUserId);
279
280 long[] organizationIds = groupUser.getOrganizationIds();
281
282 UserPermissionUtil.check(
283 permissionChecker, groupUserId, organizationIds,
284 ActionKeys.UPDATE);
285
286 if (!groupUser.isLayoutsRequired()) {
287 throw new PrincipalException();
288 }
289 }
290 }
291
292 protected void copyPreferences(
293 ActionRequest req, Layout layout, Layout copyLayout)
294 throws Exception {
295
296 long companyId = layout.getCompanyId();
297
298 LayoutTypePortlet copyLayoutTypePortlet =
299 (LayoutTypePortlet)copyLayout.getLayoutType();
300
301 List<String> copyPortletIds = copyLayoutTypePortlet.getPortletIds();
302
303 for (String copyPortletId : copyPortletIds) {
304 HttpServletRequest httpReq = PortalUtil.getHttpServletRequest(req);
305
306
308 PortletPreferencesIds portletPreferencesIds =
309 PortletPreferencesFactoryUtil.getPortletPreferencesIds(
310 httpReq, layout, copyPortletId);
311
312 PortletPreferencesLocalServiceUtil.getPreferences(
313 portletPreferencesIds);
314
315 PortletPreferencesIds copyPortletPreferencesIds =
316 PortletPreferencesFactoryUtil.getPortletPreferencesIds(
317 httpReq, copyLayout, copyPortletId);
318
319 PortletPreferences copyPrefs =
320 PortletPreferencesLocalServiceUtil.getPreferences(
321 copyPortletPreferencesIds);
322
323 PortletPreferencesLocalServiceUtil.updatePreferences(
324 portletPreferencesIds.getOwnerId(),
325 portletPreferencesIds.getOwnerType(),
326 portletPreferencesIds.getPlid(),
327 portletPreferencesIds.getPortletId(), copyPrefs);
328
329
331 PortletPreferencesLocalServiceUtil.getPreferences(
332 companyId, PortletKeys.PREFS_OWNER_ID_DEFAULT,
333 PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid(),
334 copyPortletId);
335
336 copyPrefs =
337 PortletPreferencesLocalServiceUtil.getPreferences(
338 companyId, PortletKeys.PREFS_OWNER_ID_DEFAULT,
339 PortletKeys.PREFS_OWNER_TYPE_LAYOUT, copyLayout.getPlid(),
340 copyPortletId);
341
342 PortletPreferencesLocalServiceUtil.updatePreferences(
343 PortletKeys.PREFS_OWNER_ID_DEFAULT,
344 PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid(),
345 copyPortletId, copyPrefs);
346 }
347 }
348
349 protected Properties getTypeSettingsProperties(ActionRequest req) {
350 Properties typeSettingsProperties = new SafeProperties();
351
352 String prefix = "TypeSettingsProperties(";
353
354 for (String paramName: req.getParameterMap().keySet()) {
355 if (paramName.startsWith(prefix)) {
356 String key = paramName.substring(
357 prefix.length(), paramName.length() - 1);
358
359 typeSettingsProperties.setProperty(
360 key, req.getParameter(paramName));
361 }
362 }
363
364 return typeSettingsProperties;
365 }
366
367 protected void updateDisplayOrder(ActionRequest req) throws Exception {
368 long groupId = ParamUtil.getLong(req, "groupId");
369 boolean privateLayout = ParamUtil.getBoolean(req, "privateLayout");
370 long parentLayoutId = ParamUtil.getLong(req, "parentLayoutId");
371 long[] layoutIds = StringUtil.split(
372 ParamUtil.getString(req, "layoutIds"), 0L);
373
374 LayoutServiceUtil.setLayouts(
375 groupId, privateLayout, parentLayoutId, layoutIds);
376 }
377
378 protected void updateLayout(ActionRequest req, ActionResponse res)
379 throws Exception {
380
381 UploadPortletRequest uploadReq =
382 UploadRequestUtil.getUploadPortletRequest(req);
383
384 String cmd = ParamUtil.getString(uploadReq, Constants.CMD);
385
386 long groupId = ParamUtil.getLong(req, "groupId");
387 boolean privateLayout = ParamUtil.getBoolean(req, "privateLayout");
388 long layoutId = ParamUtil.getLong(req, "layoutId");
389 long parentLayoutId = ParamUtil.getLong(uploadReq, "parentLayoutId");
390 String description = ParamUtil.getString(uploadReq, "description");
391 String type = ParamUtil.getString(uploadReq, "type");
392 boolean hidden = ParamUtil.getBoolean(uploadReq, "hidden");
393 String friendlyURL = ParamUtil.getString(uploadReq, "friendlyURL");
394 boolean iconImage = ParamUtil.getBoolean(uploadReq, "iconImage");
395 byte[] iconBytes = FileUtil.getBytes(
396 uploadReq.getFile("iconFileName"));
397
398 boolean inheritFromParentLayoutId = ParamUtil.getBoolean(
399 uploadReq, "inheritFromParentLayoutId");
400
401 long copyLayoutId = ParamUtil.getLong(uploadReq, "copyLayoutId");
402
403 Locale[] locales = LanguageUtil.getAvailableLocales();
404
405 Map<Locale, String> localeNamesMap = new HashMap<Locale, String>();
406 Map<Locale, String> localeTitlesMap = new HashMap<Locale, String>();
407
408 for (Locale locale : locales) {
409 String languageId = LocaleUtil.toLanguageId(locale);
410
411 localeNamesMap.put(
412 locale, ParamUtil.getString(uploadReq, "name_" + languageId));
413 localeTitlesMap.put(
414 locale, ParamUtil.getString(uploadReq, "title_" + languageId));
415 }
416
417 if (cmd.equals(Constants.ADD)) {
418
419
421 if (inheritFromParentLayoutId && (parentLayoutId > 0)) {
422 Layout parentLayout = LayoutLocalServiceUtil.getLayout(
423 groupId, privateLayout, parentLayoutId);
424
425 Layout layout = LayoutServiceUtil.addLayout(
426 groupId, privateLayout, parentLayoutId, localeNamesMap,
427 localeTitlesMap, description, parentLayout.getType(),
428 parentLayout.isHidden(), friendlyURL);
429
430 LayoutServiceUtil.updateLayout(
431 layout.getGroupId(), layout.isPrivateLayout(),
432 layout.getLayoutId(), parentLayout.getTypeSettings());
433 }
434 else {
435 Layout layout = LayoutServiceUtil.addLayout(
436 groupId, privateLayout, parentLayoutId, localeNamesMap,
437 localeTitlesMap, description, type, hidden, friendlyURL);
438
439 if (type.equals(LayoutImpl.TYPE_PORTLET)) {
440 LayoutTypePortlet layoutTypePortlet =
441 (LayoutTypePortlet)layout.getLayoutType();
442
443 if (Validator.isNull(
444 layoutTypePortlet.getLayoutTemplateId())) {
445
446 layoutTypePortlet.setLayoutTemplateId(
447 0, PropsValues.LAYOUT_DEFAULT_TEMPLATE_ID, false);
448
449 LayoutServiceUtil.updateLayout(
450 layout.getGroupId(), layout.isPrivateLayout(),
451 layout.getLayoutId(), layout.getTypeSettings());
452 }
453 }
454 }
455 }
456 else {
457
458
460 Layout layout = LayoutLocalServiceUtil.getLayout(
461 groupId, privateLayout, layoutId);
462
463 layout = LayoutServiceUtil.updateLayout(
464 groupId, privateLayout, layoutId, layout.getParentLayoutId(),
465 localeNamesMap, localeTitlesMap, description, type, hidden,
466 friendlyURL, Boolean.valueOf(iconImage), iconBytes);
467
468 Properties formTypeSettingsProperties = getTypeSettingsProperties(
469 req);
470
471 if (type.equals(LayoutImpl.TYPE_PORTLET)) {
472 if ((copyLayoutId > 0) &&
473 (copyLayoutId != layout.getLayoutId())) {
474
475 try {
476 Layout copyLayout = LayoutLocalServiceUtil.getLayout(
477 groupId, privateLayout, copyLayoutId);
478
479 if (copyLayout.getType().equals(
480 LayoutImpl.TYPE_PORTLET)) {
481
482 LayoutServiceUtil.updateLayout(
483 groupId, privateLayout, layoutId,
484 copyLayout.getTypeSettings());
485
486 copyPreferences(req, layout, copyLayout);
487 }
488 }
489 catch (NoSuchLayoutException nsle) {
490 }
491 }
492 else {
493 Properties layoutTypeSettingsProperties =
494 layout.getTypeSettingsProperties();
495
496 for (Object property: formTypeSettingsProperties.keySet()) {
497 layoutTypeSettingsProperties.put(
498 property, formTypeSettingsProperties.get(property));
499 }
500
501 LayoutServiceUtil.updateLayout(
502 groupId, privateLayout, layoutId,
503 layout.getTypeSettings());
504 }
505 }
506 else {
507 layout.setTypeSettingsProperties(formTypeSettingsProperties);
508
509 LayoutServiceUtil.updateLayout(
510 groupId, privateLayout, layoutId, layout.getTypeSettings());
511 }
512
513 HttpServletResponse httpRes =
514 ((ActionResponseImpl)res).getHttpServletResponse();
515
516 String[] eventClasses = StringUtil.split(
517 PropsUtil.getComponentProperties().getString(
518 PropsUtil.LAYOUT_CONFIGURATION_ACTION_UPDATE,
519 Filter.by(type)));
520
521 EventsProcessor.process(eventClasses, uploadReq, httpRes);
522 }
523 }
524
525 protected void updateLogo(ActionRequest req) throws Exception {
526 UploadPortletRequest uploadReq =
527 UploadRequestUtil.getUploadPortletRequest(req);
528
529 long liveGroupId = ParamUtil.getLong(req, "liveGroupId");
530 long stagingGroupId = ParamUtil.getLong(req, "stagingGroupId");
531
532 boolean privateLayout = ParamUtil.getBoolean(req, "privateLayout");
533 boolean logo = ParamUtil.getBoolean(req, "logo");
534
535 File file = uploadReq.getFile("logoFileName");
536 byte[] bytes = FileUtil.getBytes(file);
537
538 if (logo && ((bytes == null) || (bytes.length == 0))) {
539 throw new UploadException();
540 }
541
542 LayoutSetServiceUtil.updateLogo(liveGroupId, privateLayout, logo, file);
543
544 if (stagingGroupId > 0) {
545 LayoutSetServiceUtil.updateLogo(
546 stagingGroupId, privateLayout, logo, file);
547 }
548 }
549
550 protected void updateLookAndFeel(ActionRequest req) throws Exception {
551 ThemeDisplay themeDisplay = (ThemeDisplay)req.getAttribute(
552 WebKeys.THEME_DISPLAY);
553
554 long companyId = themeDisplay.getCompanyId();
555
556 long liveGroupId = ParamUtil.getLong(req, "liveGroupId");
557 long stagingGroupId = ParamUtil.getLong(req, "stagingGroupId");
558
559 boolean privateLayout = ParamUtil.getBoolean(req, "privateLayout");
560 long layoutId = ParamUtil.getLong(req, "layoutId");
561 String themeId = ParamUtil.getString(req, "themeId");
562 String colorSchemeId = ParamUtil.getString(req, "colorSchemeId");
563 String css = ParamUtil.getString(req, "css");
564 boolean wapTheme = ParamUtil.getBoolean(req, "wapTheme");
565
566 updateLookAndFeel(
567 companyId, liveGroupId, privateLayout, layoutId, themeId,
568 colorSchemeId, css, wapTheme);
569
570 if (stagingGroupId > 0) {
571 updateLookAndFeel(
572 companyId, stagingGroupId, privateLayout, layoutId, themeId,
573 colorSchemeId, css, wapTheme);
574 }
575 }
576
577 protected void updateLookAndFeel(
578 long companyId, long groupId, boolean privateLayout, long layoutId,
579 String themeId, String colorSchemeId, String css, boolean wapTheme)
580 throws Exception {
581
582 if (Validator.isNotNull(themeId) && Validator.isNull(colorSchemeId)) {
583 ColorScheme colorScheme = ThemeLocalUtil.getColorScheme(
584 companyId, themeId, colorSchemeId, wapTheme);
585
586 colorSchemeId = colorScheme.getColorSchemeId();
587 }
588
589 if (layoutId <= 0) {
590 LayoutSetServiceUtil.updateLookAndFeel(
591 groupId, privateLayout, themeId, colorSchemeId, css, wapTheme);
592 }
593 else {
594 LayoutServiceUtil.updateLookAndFeel(
595 groupId, privateLayout, layoutId, themeId, colorSchemeId, css,
596 wapTheme);
597 }
598 }
599
600 protected void updateMergePages(ActionRequest req) throws Exception {
601 long liveGroupId = ParamUtil.getLong(req, "liveGroupId");
602
603 boolean mergeGuestPublicPages = ParamUtil.getBoolean(
604 req, "mergeGuestPublicPages");
605
606 Group liveGroup = GroupLocalServiceUtil.getGroup(liveGroupId);
607
608 Properties props = liveGroup.getTypeSettingsProperties();
609
610 props.setProperty(
611 "mergeGuestPublicPages", String.valueOf(mergeGuestPublicPages));
612
613 GroupServiceUtil.updateGroup(liveGroupId, liveGroup.getTypeSettings());
614 }
615
616 protected void updateMonitoring(ActionRequest req) throws Exception {
617 long liveGroupId = ParamUtil.getLong(req, "liveGroupId");
618
619 String googleAnalyticsId = ParamUtil.getString(
620 req, "googleAnalyticsId");
621
622 Group liveGroup = GroupLocalServiceUtil.getGroup(liveGroupId);
623
624 Properties props = liveGroup.getTypeSettingsProperties();
625
626 props.setProperty("googleAnalyticsId", googleAnalyticsId);
627
628 GroupServiceUtil.updateGroup(liveGroupId, liveGroup.getTypeSettings());
629 }
630
631 protected void updateVirtualHost(ActionRequest req) throws Exception {
632 long liveGroupId = ParamUtil.getLong(req, "liveGroupId");
633
634 String publicVirtualHost = ParamUtil.getString(
635 req, "publicVirtualHost");
636 String privateVirtualHost = ParamUtil.getString(
637 req, "privateVirtualHost");
638 String friendlyURL = ParamUtil.getString(req, "friendlyURL");
639
640 LayoutSetServiceUtil.updateVirtualHost(
641 liveGroupId, false, publicVirtualHost);
642
643 LayoutSetServiceUtil.updateVirtualHost(
644 liveGroupId, true, privateVirtualHost);
645
646 GroupServiceUtil.updateFriendlyURL(liveGroupId, friendlyURL);
647 }
648
649 protected void updateWorkflow(ActionRequest req) throws Exception {
650 long liveGroupId = ParamUtil.getLong(req, "liveGroupId");
651
652 boolean workflowEnabled = ParamUtil.getBoolean(req, "workflowEnabled");
653 int workflowStages = ParamUtil.getInteger(req, "workflowStages");
654
655 StringMaker sm = new StringMaker();
656
657 for (int i = 1; i <= workflowStages; i++) {
658 String workflowRoleName = ParamUtil.getString(
659 req, "workflowRoleName_" + i);
660
661 sm.append(workflowRoleName);
662
663 if ((i + 1) <= workflowStages) {
664 sm.append(",");
665 }
666 }
667
668 String workflowRoleNames = sm.toString();
669
670 GroupServiceUtil.updateWorkflow(
671 liveGroupId, workflowEnabled, workflowStages, workflowRoleNames);
672 }
673
674 }