001
014
015 package com.liferay.portal.lar;
016
017 import com.liferay.portal.kernel.cluster.ClusterExecutorUtil;
018 import com.liferay.portal.kernel.cluster.ClusterRequest;
019 import com.liferay.portal.kernel.lar.PortletDataContext;
020 import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.util.ColorSchemeFactoryUtil;
024 import com.liferay.portal.kernel.util.FileUtil;
025 import com.liferay.portal.kernel.util.GetterUtil;
026 import com.liferay.portal.kernel.util.MapUtil;
027 import com.liferay.portal.kernel.util.MethodHandler;
028 import com.liferay.portal.kernel.util.MethodKey;
029 import com.liferay.portal.kernel.util.StringBundler;
030 import com.liferay.portal.kernel.util.StringPool;
031 import com.liferay.portal.kernel.util.StringUtil;
032 import com.liferay.portal.kernel.util.Time;
033 import com.liferay.portal.kernel.util.Validator;
034 import com.liferay.portal.kernel.xml.Attribute;
035 import com.liferay.portal.kernel.xml.Element;
036 import com.liferay.portal.kernel.zip.ZipReader;
037 import com.liferay.portal.kernel.zip.ZipReaderFactoryUtil;
038 import com.liferay.portal.model.Layout;
039 import com.liferay.portal.model.LayoutSet;
040 import com.liferay.portal.model.PortletConstants;
041 import com.liferay.portal.service.LayoutLocalServiceUtil;
042 import com.liferay.portal.service.LayoutSetLocalServiceUtil;
043 import com.liferay.portal.theme.ThemeLoader;
044 import com.liferay.portal.theme.ThemeLoaderFactory;
045 import com.liferay.portal.util.PortalUtil;
046 import com.liferay.portal.util.PropsValues;
047
048 import java.io.InputStream;
049
050 import java.util.List;
051 import java.util.Map;
052
053 import org.apache.commons.lang.time.StopWatch;
054
055
058 public class ThemeImporter {
059
060 public void importTheme(
061 PortletDataContext portletDataContext, Layout layout)
062 throws Exception {
063
064 boolean importTheme = MapUtil.getBoolean(
065 portletDataContext.getParameterMap(), PortletDataHandlerKeys.THEME);
066
067 if (_log.isDebugEnabled()) {
068 _log.debug("Import theme " + importTheme);
069 }
070
071 if (!importTheme || layout.isInheritLookAndFeel()) {
072 return;
073 }
074
075 StringBundler sb = new StringBundler(4);
076
077 sb.append("theme");
078 sb.append(StringPool.DASH);
079 sb.append(layout.getLayoutId());
080 sb.append(".zip");
081
082 InputStream themeZipInputStream =
083 portletDataContext.getZipEntryAsInputStream(sb.toString());
084
085 if (themeZipInputStream != null) {
086 String themeId = layout.getThemeId();
087 String colorSchemeId = layout.getColorSchemeId();
088
089 long groupId = portletDataContext.getGroupId();
090 boolean privateLayout = portletDataContext.isPrivateLayout();
091
092 Map<Long, Layout> newLayoutsMap =
093 (Map<Long, Layout>)portletDataContext.getNewPrimaryKeysMap(
094 Layout.class + ".layout");
095
096 Layout importedLayout = newLayoutsMap.get(layout.getLayoutId());
097
098 long layoutId = importedLayout.getLayoutId();
099
100 String importThemeId = importTheme(
101 groupId, privateLayout, layoutId, themeZipInputStream);
102
103 if (importThemeId != null) {
104 themeId = importThemeId;
105
106 colorSchemeId =
107 ColorSchemeFactoryUtil.getDefaultRegularColorSchemeId();
108 }
109
110 LayoutLocalServiceUtil.updateLookAndFeel(
111 groupId, privateLayout, layoutId, themeId, colorSchemeId,
112 importedLayout.getCss(), false);
113 }
114 }
115
116 public void importTheme(
117 PortletDataContext portletDataContext, LayoutSet layoutSet)
118 throws Exception {
119
120 boolean importTheme = MapUtil.getBoolean(
121 portletDataContext.getParameterMap(), PortletDataHandlerKeys.THEME);
122 boolean importThemeSettings = MapUtil.getBoolean(
123 portletDataContext.getParameterMap(),
124 PortletDataHandlerKeys.THEME_REFERENCE);
125
126 if (_log.isDebugEnabled()) {
127 _log.debug("Import theme " + importTheme);
128 _log.debug("Import theme settings " + importThemeSettings);
129 }
130
131 Element importDataRootElement =
132 portletDataContext.getImportDataRootElement();
133 Element headerElement = importDataRootElement.element("header");
134
135 String themeId = layoutSet.getThemeId();
136 String colorSchemeId = layoutSet.getColorSchemeId();
137
138 if (importThemeSettings) {
139 Attribute themeIdAttribute = headerElement.attribute("theme-id");
140
141 if (themeIdAttribute != null) {
142 themeId = themeIdAttribute.getValue();
143 }
144
145 Attribute colorSchemeIdAttribute = headerElement.attribute(
146 "color-scheme-id");
147
148 if (colorSchemeIdAttribute != null) {
149 colorSchemeId = colorSchemeIdAttribute.getValue();
150 }
151 }
152
153 InputStream themeZipInputStream = null;
154
155 if (importTheme) {
156 themeZipInputStream = portletDataContext.getZipEntryAsInputStream(
157 "theme.zip");
158 }
159
160 if (themeZipInputStream != null) {
161 StopWatch stopWatch = null;
162
163 if (_log.isDebugEnabled()) {
164 stopWatch = new StopWatch();
165
166 stopWatch.start();
167 }
168
169 String importThemeId = importTheme(
170 layoutSet.getGroupId(), layoutSet.isPrivateLayout(), 0,
171 themeZipInputStream);
172
173 if (importThemeId != null) {
174 themeId = importThemeId;
175 colorSchemeId =
176 ColorSchemeFactoryUtil.getDefaultRegularColorSchemeId();
177 }
178
179 if (_log.isDebugEnabled()) {
180 _log.debug(
181 "Importing theme takes " + stopWatch.getTime() + " ms");
182 }
183 }
184
185 String css = GetterUtil.getString(headerElement.elementText("css"));
186
187 LayoutSetLocalServiceUtil.updateLookAndFeel(
188 layoutSet.getGroupId(), layoutSet.isPrivateLayout(), themeId,
189 colorSchemeId, css, false);
190 }
191
192 protected String importTheme(
193 long groupId, boolean privateLayout, long layoutId,
194 InputStream themeZipInputStream)
195 throws Exception {
196
197 ThemeLoader themeLoader = ThemeLoaderFactory.getDefaultThemeLoader();
198
199 if (themeLoader == null) {
200 _log.error("No theme loaders are deployed");
201
202 return null;
203 }
204
205 ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(
206 themeZipInputStream);
207
208 String lookAndFeelXML = zipReader.getEntryAsString(
209 "liferay-look-and-feel.xml");
210
211 StringBundler sb = new StringBundler();
212
213 sb.append(String.valueOf(groupId));
214
215 if (privateLayout) {
216 sb.append("-private");
217 }
218 else {
219 sb.append("-public");
220 }
221
222 if (Validator.isNotNull(layoutId)) {
223 sb.append(StringPool.DASH);
224 sb.append(String.valueOf(layoutId));
225 }
226
227 if (PropsValues.THEME_LOADER_NEW_THEME_ID_ON_IMPORT) {
228 sb.append(StringPool.DASH);
229 sb.append(Time.getShortTimestamp());
230 }
231
232 String themeId = sb.toString();
233
234 lookAndFeelXML = StringUtil.replace(
235 lookAndFeelXML,
236 new String[] {
237 "[$GROUP_ID$]", "[$THEME_ID$]", "[$THEME_NAME$]"
238 },
239 new String[] {
240 String.valueOf(groupId), themeId, themeId
241 }
242 );
243
244 FileUtil.deltree(
245 themeLoader.getFileStorage() + StringPool.SLASH + themeId);
246
247 List<String> zipEntries = zipReader.getEntries();
248
249 for (String zipEntry : zipEntries) {
250 String key = zipEntry;
251
252 sb = new StringBundler(5);
253
254 sb.append(themeLoader.getFileStorage());
255 sb.append(StringPool.SLASH);
256 sb.append(themeId);
257 sb.append(StringPool.SLASH);
258 sb.append(key);
259
260 String fileName = sb.toString();
261
262 if (key.equals("liferay-look-and-feel.xml")) {
263 FileUtil.write(fileName, lookAndFeelXML.getBytes());
264 }
265 else {
266 InputStream is = zipReader.getEntryAsInputStream(zipEntry);
267
268 FileUtil.write(fileName, is);
269 }
270 }
271
272 themeLoader.loadThemes();
273
274 ClusterRequest clusterRequest = ClusterRequest.createMulticastRequest(
275 _loadThemesMethodHandler, true);
276
277 clusterRequest.setFireAndForget(true);
278
279 ClusterExecutorUtil.execute(clusterRequest);
280
281 themeId +=
282 PortletConstants.WAR_SEPARATOR +
283 themeLoader.getServletContextName();
284
285 return PortalUtil.getJsSafePortletId(themeId);
286 }
287
288 private static Log _log = LogFactoryUtil.getLog(ThemeImporter.class);
289
290 private static MethodHandler _loadThemesMethodHandler = new MethodHandler(
291 new MethodKey(ThemeLoaderFactory.class, "loadThemes"));
292
293 }