1
19
20 package com.liferay.portal.lar;
21
22 import com.liferay.portal.PortalException;
23 import com.liferay.portal.SystemException;
24 import com.liferay.portal.kernel.io.FileCacheOutputStream;
25 import com.liferay.portal.kernel.log.Log;
26 import com.liferay.portal.kernel.log.LogFactoryUtil;
27 import com.liferay.portal.kernel.util.FileUtil;
28 import com.liferay.portal.kernel.util.MapUtil;
29 import com.liferay.portal.kernel.util.ReleaseInfo;
30 import com.liferay.portal.kernel.util.StringPool;
31 import com.liferay.portal.kernel.util.StringUtil;
32 import com.liferay.portal.kernel.util.Time;
33 import com.liferay.portal.kernel.xml.Document;
34 import com.liferay.portal.kernel.xml.Element;
35 import com.liferay.portal.kernel.xml.SAXReaderUtil;
36 import com.liferay.portal.kernel.zip.ZipWriter;
37 import com.liferay.portal.model.Group;
38 import com.liferay.portal.model.GroupConstants;
39 import com.liferay.portal.model.Image;
40 import com.liferay.portal.model.Layout;
41 import com.liferay.portal.model.LayoutConstants;
42 import com.liferay.portal.model.LayoutSet;
43 import com.liferay.portal.model.LayoutTypePortlet;
44 import com.liferay.portal.model.Portlet;
45 import com.liferay.portal.model.PortletConstants;
46 import com.liferay.portal.model.Resource;
47 import com.liferay.portal.model.ResourceConstants;
48 import com.liferay.portal.model.Theme;
49 import com.liferay.portal.service.GroupLocalServiceUtil;
50 import com.liferay.portal.service.ImageLocalServiceUtil;
51 import com.liferay.portal.service.LayoutLocalServiceUtil;
52 import com.liferay.portal.service.LayoutSetLocalServiceUtil;
53 import com.liferay.portal.service.PortletLocalServiceUtil;
54 import com.liferay.portal.service.UserLocalServiceUtil;
55 import com.liferay.portal.service.permission.PortletPermissionUtil;
56 import com.liferay.portal.service.persistence.LayoutUtil;
57 import com.liferay.portal.theme.ThemeLoader;
58 import com.liferay.portal.theme.ThemeLoaderFactory;
59 import com.liferay.portal.util.ContentUtil;
60 import com.liferay.portal.util.PortletKeys;
61 import com.liferay.portal.util.PropsValues;
62 import com.liferay.portal.velocity.VelocityContextPool;
63
64 import java.io.File;
65 import java.io.IOException;
66 import java.io.InputStream;
67
68 import java.util.Date;
69 import java.util.HashSet;
70 import java.util.LinkedHashMap;
71 import java.util.List;
72 import java.util.Map;
73
74 import javax.servlet.ServletContext;
75
76 import org.apache.commons.lang.time.StopWatch;
77
78
89 public class LayoutExporter {
90
91 public byte[] exportLayouts(
92 long groupId, boolean privateLayout, long[] layoutIds,
93 Map<String, String[]> parameterMap, Date startDate, Date endDate)
94 throws PortalException, SystemException {
95
96 FileCacheOutputStream fcos = exportLayoutsAsStream(
97 groupId, privateLayout, layoutIds, parameterMap, startDate,
98 endDate);
99
100 try {
101 return fcos.getBytes();
102 }
103 catch (IOException ioe) {
104 throw new SystemException(ioe);
105 }
106 }
107
108 public FileCacheOutputStream exportLayoutsAsStream(
109 long groupId, boolean privateLayout, long[] layoutIds,
110 Map<String, String[]> parameterMap, Date startDate, Date endDate)
111 throws PortalException, SystemException {
112
113 boolean exportPermissions = MapUtil.getBoolean(
114 parameterMap, PortletDataHandlerKeys.PERMISSIONS);
115 boolean exportUserPermissions = MapUtil.getBoolean(
116 parameterMap, PortletDataHandlerKeys.USER_PERMISSIONS);
117 boolean exportPortletData = MapUtil.getBoolean(
118 parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
119 boolean exportPortletSetup = MapUtil.getBoolean(
120 parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
121 boolean exportPortletArchivedSetups = MapUtil.getBoolean(
122 parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
123 boolean exportPortletUserPreferences = MapUtil.getBoolean(
124 parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
125 boolean exportTheme = MapUtil.getBoolean(
126 parameterMap, PortletDataHandlerKeys.THEME);
127
128 if (_log.isDebugEnabled()) {
129 _log.debug("Export permissions " + exportPermissions);
130 _log.debug("Export user permissions " + exportUserPermissions);
131 _log.debug("Export portlet data " + exportPortletData);
132 _log.debug("Export portlet setup " + exportPortletSetup);
133 _log.debug(
134 "Export portlet archived setups " +
135 exportPortletArchivedSetups);
136 _log.debug(
137 "Export portlet user preferences " +
138 exportPortletUserPreferences);
139 _log.debug("Export theme " + exportTheme);
140 }
141
142 StopWatch stopWatch = null;
143
144 if (_log.isInfoEnabled()) {
145 stopWatch = new StopWatch();
146
147 stopWatch.start();
148 }
149
150 LayoutCache layoutCache = new LayoutCache();
151
152 LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
153 groupId, privateLayout);
154
155 long companyId = layoutSet.getCompanyId();
156 long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);
157
158 ZipWriter zipWriter = null;
159
160 try {
161 zipWriter = new ZipWriter();
162 }
163 catch (IOException ioe) {
164 throw new SystemException(ioe);
165 }
166
167 PortletDataContext context = new PortletDataContextImpl(
168 companyId, groupId, parameterMap, new HashSet<String>(), startDate,
169 endDate, zipWriter);
170
171 Group guestGroup = GroupLocalServiceUtil.getGroup(
172 companyId, GroupConstants.GUEST);
173
174
176 Document doc = SAXReaderUtil.createDocument();
177
178 Element root = doc.addElement("root");
179
180 Element header = root.addElement("header");
181
182 header.addAttribute(
183 "build-number", String.valueOf(ReleaseInfo.getBuildNumber()));
184 header.addAttribute("export-date", Time.getRFC822());
185
186 if (context.hasDateRange()) {
187 header.addAttribute(
188 "start-date", String.valueOf(context.getStartDate()));
189 header.addAttribute(
190 "end-date", String.valueOf(context.getEndDate()));
191 }
192
193 header.addAttribute("type", "layout-set");
194 header.addAttribute("group-id", String.valueOf(groupId));
195 header.addAttribute("private-layout", String.valueOf(privateLayout));
196 header.addAttribute("theme-id", layoutSet.getThemeId());
197 header.addAttribute("color-scheme-id", layoutSet.getColorSchemeId());
198
199
201 Portlet layoutConfigurationPortlet =
202 PortletLocalServiceUtil.getPortletById(
203 context.getCompanyId(), PortletKeys.LAYOUT_CONFIGURATION);
204
205
207 Map<String, Object[]> portletIds =
208 new LinkedHashMap<String, Object[]>();
209
210 List<Layout> layouts = null;
211
212 if ((layoutIds == null) || (layoutIds.length == 0)) {
213 layouts = LayoutLocalServiceUtil.getLayouts(groupId, privateLayout);
214 }
215 else {
216 layouts = LayoutLocalServiceUtil.getLayouts(
217 groupId, privateLayout, layoutIds);
218 }
219
220 Element layoutsEl = root.addElement("layouts");
221
222 for (Layout layout : layouts) {
223 context.setPlid(layout.getPlid());
224
225 Document layoutDoc = SAXReaderUtil.createDocument();
226
227 Element layoutEl = layoutDoc.addElement("layout");
228
229 layoutEl.addAttribute("old-plid", String.valueOf(layout.getPlid()));
230 layoutEl.addAttribute(
231 "layout-id", String.valueOf(layout.getLayoutId()));
232 layoutEl.addElement("parent-layout-id").addText(
233 String.valueOf(layout.getParentLayoutId()));
234 layoutEl.addElement("name").addCDATA(layout.getName());
235 layoutEl.addElement("title").addCDATA(layout.getTitle());
236 layoutEl.addElement("description").addText(layout.getDescription());
237 layoutEl.addElement("type").addText(layout.getType());
238 layoutEl.addElement("type-settings").addCDATA(
239 layout.getTypeSettings());
240 layoutEl.addElement("hidden").addText(
241 String.valueOf(layout.getHidden()));
242 layoutEl.addElement("friendly-url").addText(
243 layout.getFriendlyURL());
244 layoutEl.addElement("icon-image").addText(
245 String.valueOf(layout.getIconImage()));
246
247 if (layout.isIconImage()) {
248 Image image = ImageLocalServiceUtil.getImage(
249 layout.getIconImageId());
250
251 if (image != null) {
252 String iconPath = getLayoutIconPath(context, layout, image);
253
254 layoutEl.addElement("icon-image-path").addText(
255 iconPath);
256
257 context.addZipEntry(iconPath, image.getTextObj());
258 }
259 }
260
261 layoutEl.addElement("theme-id").addText(layout.getThemeId());
262 layoutEl.addElement("color-scheme-id").addText(
263 layout.getColorSchemeId());
264 layoutEl.addElement("wap-theme-id").addText(layout.getWapThemeId());
265 layoutEl.addElement("wap-color-scheme-id").addText(
266 layout.getWapColorSchemeId());
267 layoutEl.addElement("css").addCDATA(layout.getCss());
268 layoutEl.addElement("priority").addText(
269 String.valueOf(layout.getPriority()));
270
271
273 if (exportPermissions) {
274 Element permissionsEl = layoutEl.addElement("permissions");
275
276 String resourceName = Layout.class.getName();
277 String resourcePrimKey = String.valueOf(layout.getPlid());
278
279 if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
280 exportLayoutPermissions_5(
281 layoutCache, companyId, groupId, resourceName,
282 resourcePrimKey, permissionsEl);
283 }
284 else {
285 exportLayoutPermissions_4(
286 layoutCache, companyId, groupId, guestGroup,
287 resourceName, resourcePrimKey, permissionsEl,
288 exportUserPermissions);
289 }
290 }
291
292 if (layout.getType().equals(LayoutConstants.TYPE_PORTLET)) {
293 LayoutTypePortlet layoutTypePortlet =
294 (LayoutTypePortlet)layout.getLayoutType();
295
296 for (String portletId : layoutTypePortlet.getPortletIds()) {
297 String key = PortletPermissionUtil.getPrimaryKey(
298 layout.getPlid(), portletId);
299
300 portletIds.put(
301 key, new Object[] {portletId, layout.getPlid()});
302 }
303 }
304
305 String layoutPath = context.getLayoutPath(layout.getLayoutId()) +
306 "/layout.xml";
307
308 Element el = layoutsEl.addElement("layout");
309
310 el.addAttribute("layout-id", String.valueOf(layout.getLayoutId()));
311 el.addAttribute("path", layoutPath);
312
313 _portletExporter.exportPortletData(
314 context, layoutConfigurationPortlet, layout, null, layoutEl);
315
316 try {
317 context.addZipEntry(layoutPath, layoutDoc.formattedString());
318 }
319 catch (IOException ioe) {
320 }
321 }
322
323 if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM != 5) {
324 Element rolesEl = root.addElement("roles");
325
326
328 if (exportPermissions) {
329 exportLayoutRoles(layoutCache, companyId, groupId, rolesEl);
330 }
331 }
332
333
335 Element portletsEl = root.addElement("portlets");
336
337 for (Map.Entry<String, Object[]> portletIdsEntry :
338 portletIds.entrySet()) {
339
340 String portletId = (String)portletIdsEntry.getValue()[0];
341 String rootPortletId = PortletConstants.getRootPortletId(portletId);
342 long plid = (Long)portletIdsEntry.getValue()[1];
343
344 Layout layout = LayoutUtil.findByPrimaryKey(plid);
345
346 context.setPlid(layout.getPlid());
347 context.setOldPlid(layout.getPlid());
348
349 boolean exportCurPortletData = exportPortletData;
350 boolean exportCurPortletSetup = exportPortletSetup;
351
352 Portlet portlet = PortletLocalServiceUtil.getPortletById(
353 context.getCompanyId(), portletId);
354
355 if (portlet != null) {
356 String portletDataHandlerClass =
357 portlet.getPortletDataHandlerClass();
358
359 if (portletDataHandlerClass != null) {
360 exportCurPortletData =
361 exportPortletData &&
362 MapUtil.getBoolean(
363 parameterMap,
364 PortletDataHandlerKeys.PORTLET_DATA +
365 StringPool.UNDERLINE + rootPortletId);
366
367 exportCurPortletSetup =
368 exportPortletSetup &&
369 MapUtil.getBoolean(
370 parameterMap,
371 PortletDataHandlerKeys.PORTLET_SETUP +
372 StringPool.UNDERLINE + rootPortletId);
373 }
374 }
375
376 _portletExporter.exportPortlet(
377 context, layoutCache, portletId, layout, portletsEl,
378 defaultUserId, exportPermissions, exportPortletArchivedSetups,
379 exportCurPortletData, exportCurPortletSetup,
380 exportPortletUserPreferences, exportUserPermissions);
381 }
382
383
385 _portletExporter.exportComments(context, root);
386
387
389 _portletExporter.exportRatings(context, root);
390
391
393 _portletExporter.exportTags(context, root);
394
395
397 InputStream themeZip = null;
398
399 try {
400 if (exportTheme) {
401 themeZip = exportTheme(layoutSet).getFileInputStream();
402 }
403 }
404 catch (IOException ioe) {
405 throw new SystemException(ioe);
406 }
407
408
410 if (_log.isInfoEnabled()) {
411 _log.info("Exporting layouts takes " + stopWatch.getTime() + " ms");
412 }
413
414
416 try {
417 context.addZipEntry("/manifest.xml", doc.formattedString());
418
419 if (themeZip != null) {
420 context.addZipEntry("/theme.zip", themeZip);
421 }
422
423 return zipWriter.finishWithStream();
424 }
425 catch (IOException ioe) {
426 throw new SystemException(ioe);
427 }
428 }
429
430 protected void exportLayoutPermissions_4(
431 LayoutCache layoutCache, long companyId, long groupId,
432 Group guestGroup, String resourceName, String resourcePrimKey,
433 Element permissionsEl, boolean exportUserPermissions)
434 throws SystemException {
435
436 _portletExporter.exportGroupPermissions(
437 companyId, groupId, resourceName, resourcePrimKey, permissionsEl,
438 "community-actions");
439
440 if (groupId != guestGroup.getGroupId()) {
441 _portletExporter.exportGroupPermissions(
442 companyId, guestGroup.getGroupId(), resourceName,
443 resourcePrimKey, permissionsEl, "guest-actions");
444 }
445
446 if (exportUserPermissions) {
447 _portletExporter.exportUserPermissions(
448 layoutCache, companyId, groupId, resourceName, resourcePrimKey,
449 permissionsEl);
450 }
451
452 _portletExporter.exportInheritedPermissions(
453 layoutCache, companyId, resourceName, resourcePrimKey,
454 permissionsEl, "organization");
455
456 _portletExporter.exportInheritedPermissions(
457 layoutCache, companyId, resourceName, resourcePrimKey,
458 permissionsEl, "location");
459
460 _portletExporter.exportInheritedPermissions(
461 layoutCache, companyId, resourceName, resourcePrimKey,
462 permissionsEl, "user-group");
463 }
464
465 protected void exportLayoutPermissions_5(
466 LayoutCache layoutCache, long companyId, long groupId,
467 String resourceName, String resourcePrimKey, Element permissionsEl)
468 throws PortalException, SystemException {
469
470 boolean portletActions = false;
471
472 Resource resource = layoutCache.getResource(
473 companyId, groupId, resourceName,
474 ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey,
475 portletActions);
476
477 _portletExporter.exportPermissions_5(
478 layoutCache, groupId, resourceName, resource.getResourceId(),
479 permissionsEl);
480 }
481
482 protected void exportLayoutRoles(
483 LayoutCache layoutCache, long companyId, long groupId,
484 Element rolesEl)
485 throws SystemException {
486
487 String resourceName = Layout.class.getName();
488
489 _portletExporter.exportGroupRoles(
490 layoutCache, companyId, groupId, resourceName, "community",
491 rolesEl);
492
493 _portletExporter.exportUserRoles(
494 layoutCache, companyId, groupId, resourceName, rolesEl);
495
496 _portletExporter.exportInheritedRoles(
497 layoutCache, companyId, groupId, resourceName, "organization",
498 rolesEl);
499
500 _portletExporter.exportInheritedRoles(
501 layoutCache, companyId, groupId, resourceName, "location", rolesEl);
502
503 _portletExporter.exportInheritedRoles(
504 layoutCache, companyId, groupId, resourceName, "user-group",
505 rolesEl);
506 }
507
508 protected FileCacheOutputStream exportTheme(LayoutSet layoutSet)
509 throws IOException {
510
511 Theme theme = layoutSet.getTheme();
512
513 ZipWriter zipWriter = new ZipWriter();
514
515 String lookAndFeelXML = ContentUtil.get(
516 "com/liferay/portal/dependencies/liferay-look-and-feel.xml.tmpl");
517
518 lookAndFeelXML = StringUtil.replace(
519 lookAndFeelXML,
520 new String[] {
521 "[$TEMPLATE_EXTENSION$]", "[$VIRTUAL_PATH$]"
522 },
523 new String[] {
524 theme.getTemplateExtension(), theme.getVirtualPath()
525 }
526 );
527
528 zipWriter.addEntry("liferay-look-and-feel.xml", lookAndFeelXML);
529
530 String servletContextName = theme.getServletContextName();
531
532 ServletContext servletContext = VelocityContextPool.get(
533 servletContextName);
534
535 if (servletContext == null) {
536 if (_log.isWarnEnabled()) {
537 _log.warn(
538 "Servlet context not found for theme " +
539 theme.getThemeId());
540 }
541
542 return null;
543 }
544
545 File cssPath = null;
546 File imagesPath = null;
547 File javaScriptPath = null;
548 File templatesPath = null;
549
550 if (!theme.isLoadFromServletContext()) {
551 ThemeLoader themeLoader = ThemeLoaderFactory.getThemeLoader(
552 servletContextName);
553
554 if (themeLoader == null) {
555 _log.error(
556 servletContextName + " does not map to a theme loader");
557 }
558 else {
559 String realPath =
560 themeLoader.getFileStorage().getPath() + "/" +
561 theme.getName();
562
563 cssPath = new File(realPath + "/css");
564 imagesPath = new File(realPath + "/images");
565 javaScriptPath = new File(realPath + "/javascript");
566 templatesPath = new File(realPath + "/templates");
567 }
568 }
569 else {
570 cssPath = new File(servletContext.getRealPath(theme.getCssPath()));
571 imagesPath = new File(
572 servletContext.getRealPath(theme.getImagesPath()));
573 javaScriptPath = new File(
574 servletContext.getRealPath(theme.getJavaScriptPath()));
575 templatesPath = new File(
576 servletContext.getRealPath(theme.getTemplatesPath()));
577 }
578
579 exportThemeFiles("css", cssPath, zipWriter);
580 exportThemeFiles("images", imagesPath, zipWriter);
581 exportThemeFiles("javascript", javaScriptPath, zipWriter);
582 exportThemeFiles("templates", templatesPath, zipWriter);
583
584 return zipWriter.finishWithStream();
585 }
586
587 protected void exportThemeFiles(String path, File dir, ZipWriter zipWriter)
588 throws IOException {
589
590 if ((dir == null) || (!dir.exists())) {
591 return;
592 }
593
594 File[] files = dir.listFiles();
595
596 for (int i = 0; i < files.length; i++) {
597 File file = files[i];
598
599 if (file.isDirectory()) {
600 exportThemeFiles(path + "/" + file.getName(), file, zipWriter);
601 }
602 else {
603 zipWriter.addEntry(
604 path + "/" + file.getName(), FileUtil.getBytes(file));
605 }
606 }
607 }
608
609 protected String getLayoutIconPath(
610 PortletDataContext context, Layout layout, Image image) {
611
612 StringBuilder sb = new StringBuilder();
613
614 sb.append(context.getLayoutPath(layout.getLayoutId()));
615 sb.append("/icons/");
616 sb.append(image.getImageId());
617 sb.append(StringPool.PERIOD);
618 sb.append(image.getType());
619
620 return sb.toString();
621 }
622
623 private static Log _log = LogFactoryUtil.getLog(LayoutExporter.class);
624
625 private PortletExporter _portletExporter = new PortletExporter();
626
627 }