001
014
015 package com.liferay.portal.model;
016
017 import com.liferay.portal.kernel.dao.orm.QueryUtil;
018 import com.liferay.portal.kernel.exception.PortalException;
019 import com.liferay.portal.kernel.exception.SystemException;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.staging.MergeLayoutPrototypesThreadLocal;
023 import com.liferay.portal.kernel.staging.StagingUtil;
024 import com.liferay.portal.kernel.util.ParamUtil;
025 import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
026 import com.liferay.portal.kernel.util.ProxyUtil;
027 import com.liferay.portal.kernel.util.ReflectionUtil;
028 import com.liferay.portal.kernel.workflow.WorkflowConstants;
029 import com.liferay.portal.service.LayoutBranchLocalServiceUtil;
030 import com.liferay.portal.service.LayoutRevisionLocalServiceUtil;
031 import com.liferay.portal.service.LayoutSetBranchLocalServiceUtil;
032 import com.liferay.portal.service.ServiceContext;
033 import com.liferay.portal.service.ServiceContextThreadLocal;
034 import com.liferay.portal.service.UserLocalServiceUtil;
035 import com.liferay.portal.util.LayoutTypePortletFactoryUtil;
036 import com.liferay.portal.util.comparator.LayoutRevisionCreateDateComparator;
037
038 import java.io.Serializable;
039
040 import java.lang.reflect.InvocationHandler;
041 import java.lang.reflect.InvocationTargetException;
042 import java.lang.reflect.Method;
043
044 import java.util.HashSet;
045 import java.util.List;
046 import java.util.Set;
047
048
052 public class LayoutStagingHandler implements InvocationHandler, Serializable {
053
054 public LayoutStagingHandler(Layout layout) {
055 this(layout, null);
056 }
057
058 public Layout getLayout() {
059 return _layout;
060 }
061
062 public LayoutRevision getLayoutRevision() {
063 return _layoutRevision;
064 }
065
066 @Override
067 public Object invoke(Object proxy, Method method, Object[] arguments)
068 throws Throwable {
069
070 try {
071 if (_layoutRevision == null) {
072 return method.invoke(_layout, arguments);
073 }
074
075 String methodName = method.getName();
076
077 if (methodName.equals("getLayoutType")) {
078 return _getLayoutType();
079 }
080 else if (methodName.equals("toEscapedModel")) {
081 if (_layout.isEscapedModel()) {
082 return this;
083 }
084
085 return _toEscapedModel();
086 }
087
088 if (methodName.equals("clone")) {
089 return _clone();
090 }
091
092 Object bean = _layout;
093
094 if (_layoutRevisionMethodNames.contains(methodName)) {
095 try {
096 Class<?> layoutRevisionClass = _layoutRevision.getClass();
097
098 method = layoutRevisionClass.getMethod(
099 methodName,
100 ReflectionUtil.getParameterTypes(arguments));
101
102 bean = _layoutRevision;
103 }
104 catch (NoSuchMethodException nsme) {
105 _log.error(nsme, nsme);
106 }
107 }
108
109 return method.invoke(bean, arguments);
110 }
111 catch (InvocationTargetException ite) {
112 throw ite.getTargetException();
113 }
114 }
115
116 public void setLayoutRevision(LayoutRevision layoutRevision) {
117 _layoutRevision = layoutRevision;
118 }
119
120 private LayoutStagingHandler(Layout layout, LayoutRevision layoutRevision) {
121 _layout = layout;
122
123 try {
124 _layoutRevision = _getLayoutRevision(layout, layoutRevision);
125 }
126 catch (Exception e) {
127 _log.error(e, e);
128
129 throw new IllegalStateException(e);
130 }
131 }
132
133 private Object _clone() {
134 return ProxyUtil.newProxyInstance(
135 PortalClassLoaderUtil.getClassLoader(), new Class[] {Layout.class},
136 new LayoutStagingHandler(_layout, _layoutRevision));
137 }
138
139 private LayoutRevision _getLayoutRevision(
140 Layout layout, LayoutRevision layoutRevision)
141 throws PortalException, SystemException {
142
143 if (layoutRevision != null) {
144 return layoutRevision;
145 }
146
147 ServiceContext serviceContext =
148 ServiceContextThreadLocal.getServiceContext();
149
150 if (!serviceContext.isSignedIn()) {
151 LayoutRevision lastLayoutRevision = null;
152
153 lastLayoutRevision =
154 LayoutRevisionLocalServiceUtil.fetchLastLayoutRevision(
155 layout.getPlid(), true);
156
157 if (lastLayoutRevision == null) {
158 lastLayoutRevision =
159 LayoutRevisionLocalServiceUtil.fetchLastLayoutRevision(
160 layout.getPlid(), false);
161 }
162
163 return lastLayoutRevision;
164 }
165
166 User user = UserLocalServiceUtil.getUser(serviceContext.getUserId());
167
168 long layoutSetBranchId = ParamUtil.getLong(
169 serviceContext, "layoutSetBranchId");
170
171 LayoutSet layoutSet = layout.getLayoutSet();
172
173 LayoutSetBranch layoutSetBranch =
174 LayoutSetBranchLocalServiceUtil.getUserLayoutSetBranch(
175 serviceContext.getUserId(), layout.getGroupId(),
176 layout.isPrivateLayout(), layoutSet.getLayoutSetId(),
177 layoutSetBranchId);
178
179 layoutSetBranchId = layoutSetBranch.getLayoutSetBranchId();
180
181 long layoutRevisionId = ParamUtil.getLong(
182 serviceContext, "layoutRevisionId");
183
184 if (layoutRevisionId <= 0) {
185 layoutRevisionId = StagingUtil.getRecentLayoutRevisionId(
186 user, layoutSetBranchId, layout.getPlid());
187 }
188
189 if (layoutRevisionId > 0) {
190 layoutRevision =
191 LayoutRevisionLocalServiceUtil.fetchLayoutRevision(
192 layoutRevisionId);
193
194 if (layoutRevision.getStatus() !=
195 WorkflowConstants.STATUS_INACTIVE) {
196
197 return layoutRevision;
198 }
199
200 layoutRevision = null;
201 }
202
203 List<LayoutRevision> layoutRevisions =
204 LayoutRevisionLocalServiceUtil.getLayoutRevisions(
205 layoutSetBranchId, layout.getPlid(), QueryUtil.ALL_POS,
206 QueryUtil.ALL_POS,
207 new LayoutRevisionCreateDateComparator(true));
208
209 if (!layoutRevisions.isEmpty()) {
210 layoutRevision = layoutRevisions.get(0);
211
212 for (LayoutRevision curLayoutRevision : layoutRevisions) {
213 if (curLayoutRevision.isHead()) {
214 layoutRevision = curLayoutRevision;
215
216 break;
217 }
218 }
219 }
220
221 if (layoutRevision != null) {
222 StagingUtil.setRecentLayoutRevisionId(
223 user, layoutSetBranchId, layout.getPlid(),
224 layoutRevision.getLayoutRevisionId());
225
226 return layoutRevision;
227 }
228
229 LayoutBranch layoutBranch =
230 LayoutBranchLocalServiceUtil.getMasterLayoutBranch(
231 layoutSetBranchId, layout.getPlid(), serviceContext);
232
233 if (!MergeLayoutPrototypesThreadLocal.isInProgress()) {
234 serviceContext.setWorkflowAction(
235 WorkflowConstants.ACTION_SAVE_DRAFT);
236 }
237
238 layoutRevision = LayoutRevisionLocalServiceUtil.addLayoutRevision(
239 serviceContext.getUserId(), layoutSetBranchId,
240 layoutBranch.getLayoutBranchId(),
241 LayoutRevisionConstants.DEFAULT_PARENT_LAYOUT_REVISION_ID, false,
242 layout.getPlid(), LayoutConstants.DEFAULT_PLID,
243 layout.isPrivateLayout(), layout.getName(), layout.getTitle(),
244 layout.getDescription(), layout.getKeywords(), layout.getRobots(),
245 layout.getTypeSettings(), layout.getIconImage(),
246 layout.getIconImageId(), layout.getThemeId(),
247 layout.getColorSchemeId(), layout.getWapThemeId(),
248 layout.getWapColorSchemeId(), layout.getCss(), serviceContext);
249
250 boolean explicitCreation = ParamUtil.getBoolean(
251 serviceContext, "explicitCreation");
252
253 if (!explicitCreation) {
254 LayoutRevisionLocalServiceUtil.updateStatus(
255 serviceContext.getUserId(),
256 layoutRevision.getLayoutRevisionId(),
257 WorkflowConstants.STATUS_INCOMPLETE, serviceContext);
258 }
259
260 return layoutRevision;
261 }
262
263 private LayoutType _getLayoutType() {
264 return LayoutTypePortletFactoryUtil.create(
265 (Layout)ProxyUtil.newProxyInstance(
266 PortalClassLoaderUtil.getClassLoader(),
267 new Class[] {Layout.class},
268 new LayoutStagingHandler(_layout, _layoutRevision)));
269 }
270
271 private Object _toEscapedModel() {
272 return ProxyUtil.newProxyInstance(
273 PortalClassLoaderUtil.getClassLoader(), new Class[] {Layout.class},
274 new LayoutStagingHandler(
275 _layout.toEscapedModel(), _layoutRevision.toEscapedModel()));
276 }
277
278 private static Log _log = LogFactoryUtil.getLog(LayoutStagingHandler.class);
279
280 private static Set<String> _layoutRevisionMethodNames =
281 new HashSet<String>();
282
283 static {
284 _layoutRevisionMethodNames.add("getColorScheme");
285 _layoutRevisionMethodNames.add("getColorSchemeId");
286 _layoutRevisionMethodNames.add("getCss");
287 _layoutRevisionMethodNames.add("getCssText");
288 _layoutRevisionMethodNames.add("getDescription");
289 _layoutRevisionMethodNames.add("getHTMLTitle");
290 _layoutRevisionMethodNames.add("getIconImage");
291 _layoutRevisionMethodNames.add("getIconImageId");
292 _layoutRevisionMethodNames.add("getKeywords");
293 _layoutRevisionMethodNames.add("getName");
294 _layoutRevisionMethodNames.add("getRobots");
295 _layoutRevisionMethodNames.add("getTheme");
296 _layoutRevisionMethodNames.add("getThemeId");
297 _layoutRevisionMethodNames.add("getTitle");
298 _layoutRevisionMethodNames.add("getTypeSettings");
299 _layoutRevisionMethodNames.add("getTypeSettingsProperties");
300 _layoutRevisionMethodNames.add("getWapColorScheme");
301 _layoutRevisionMethodNames.add("getWapColorSchemeId");
302 _layoutRevisionMethodNames.add("getWapTheme");
303 _layoutRevisionMethodNames.add("getWapThemeId");
304 _layoutRevisionMethodNames.add("hasDefaultAssetPublisherPortletId");
305 _layoutRevisionMethodNames.add("isEscapedModel");
306 _layoutRevisionMethodNames.add("isIconImage");
307 _layoutRevisionMethodNames.add("isInheritLookAndFeel");
308 _layoutRevisionMethodNames.add("isInheritWapLookAndFeel");
309 _layoutRevisionMethodNames.add("setColorSchemeId");
310 _layoutRevisionMethodNames.add("setCss");
311 _layoutRevisionMethodNames.add("setDescription");
312 _layoutRevisionMethodNames.add("setDescriptionMap");
313 _layoutRevisionMethodNames.add("setEscapedModel");
314 _layoutRevisionMethodNames.add("setIconImage");
315 _layoutRevisionMethodNames.add("setIconImageId");
316 _layoutRevisionMethodNames.add("setKeywords");
317 _layoutRevisionMethodNames.add("setKeywordsMap");
318 _layoutRevisionMethodNames.add("setName");
319 _layoutRevisionMethodNames.add("setNameMap");
320 _layoutRevisionMethodNames.add("setRobots");
321 _layoutRevisionMethodNames.add("setRobotsMap");
322 _layoutRevisionMethodNames.add("setThemeId");
323 _layoutRevisionMethodNames.add("setTitle");
324 _layoutRevisionMethodNames.add("setTitleMap");
325 _layoutRevisionMethodNames.add("setTypeSettings");
326 _layoutRevisionMethodNames.add("setTypeSettingsProperties");
327 _layoutRevisionMethodNames.add("setWapColorSchemeId");
328 _layoutRevisionMethodNames.add("setWapThemeId");
329 }
330
331 private Layout _layout;
332 private LayoutRevision _layoutRevision;
333
334 }