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