Index: portal-impl/src/com/liferay/portal/events/ExtensionPointUtil.java =================================================================== --- portal-impl/src/com/liferay/portal/events/ExtensionPointUtil.java (revision 0) +++ portal-impl/src/com/liferay/portal/events/ExtensionPointUtil.java (revision 0) @@ -0,0 +1,137 @@ +/** + * + */ +package com.liferay.portal.events; + +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.hibernate.criterion.DetachedCriteria; +import org.hibernate.criterion.MatchMode; +import org.hibernate.criterion.Order; +import org.hibernate.criterion.Restrictions; + +import com.liferay.portal.NoSuchLayoutException; +import com.liferay.portal.PortalException; +import com.liferay.portal.SystemException; +import com.liferay.portal.kernel.dao.DynamicQueryInitializer; +import com.liferay.portal.kernel.util.StringPool; +import com.liferay.portal.model.Layout; +import com.liferay.portal.model.LayoutConstants; +import com.liferay.portal.model.impl.LayoutImpl; +import com.liferay.portal.service.LayoutLocalServiceUtil; +import com.liferay.util.dao.hibernate.DynamicQueryInitializerImpl; + +/** + * @author fricke + * + */ +public class ExtensionPointUtil extends + com.liferay.portal.util.ExtensionPointUtil { + /** + * + * @param layout + * The requested layout + * @param request + * The request + * @return the extension target layout for an extension point or the + * original layout, if no extension point is requested or no target + * is known. + */ + public static Layout getExtensionTarget(Layout layout, + HttpServletRequest request, boolean deepHistory) { + if (layout == null) { + return null; + } + + Layout targetLayout = layout; + HttpSession session = request.getSession(false); + + boolean isExtensionPoint = LAYOUT_TYPE_EXTENSION_POINT + .equals(targetLayout.getType()); + // disable deepHistory if the requested layout is an extension point + // (will not come from navigation) + boolean considerDeepHistory = deepHistory && !isExtensionPoint; + while (session != null && (isExtensionPoint || considerDeepHistory)) { + + // Check if an extension point is defined for the top ancestor + String attributeName = getAttributeName(targetLayout.getPlid(), + !isExtensionPoint); + Object targetPlid = session.getAttribute(attributeName); + // if no target is known yet AND it is an extension point AND + // exactly one target is configured that target is used and stored + // as extension target. This automatism is only done for non hidden + // layouts or if deepHistory is wished + if (targetPlid == null && isExtensionPoint + && (deepHistory || !targetLayout.getHidden())) { + List targets = getAllExtensionTargets(targetLayout); + if (targets.size() == 1) { + targetPlid = new Long(((Layout) targets.get(0)).getPlid()); + session.setAttribute(attributeName, targetPlid); + } else { + session.setAttribute(attributeName, Boolean.FALSE); + } + } + + if (targetPlid instanceof Long) { + long plid = ((Long) targetPlid).longValue(); + if (plid != targetLayout.getPlid()) { + try { + targetLayout = LayoutLocalServiceUtil.getLayout(plid); + isExtensionPoint = LAYOUT_TYPE_EXTENSION_POINT + .equals(targetLayout.getType()); + continue; + } catch (NoSuchLayoutException e) { + // Session value is invalid; remove it + session.removeAttribute(attributeName); + } catch (PortalException e) { + throw new RuntimeException(e); + } catch (SystemException e) { + throw new RuntimeException(e); + } + } + } + + break; + } + + return targetLayout; + } + + /** + * @param extLayout + * an extension point layout + * @return a list of layouts that defines the given layout as extension + * point + */ + public static List getAllExtensionTargets(Layout extLayout) { + // Select all top level layouts that use the selLayout as extension + // point + DetachedCriteria criteria = DetachedCriteria.forClass(LayoutImpl.class); + criteria.add(Restrictions.eq("companyId", new Long(extLayout + .getCompanyId()))); + criteria.add(Restrictions.eq("parentLayoutId", Long + .valueOf(LayoutConstants.DEFAULT_PARENT_LAYOUT_ID))); + criteria.add(Restrictions.eq("privateLayout", Boolean.valueOf(extLayout + .isPrivateLayout()))); + criteria.add(Restrictions.ilike("typeSettings", "extension-point=" + + extLayout.getGroup().getName() + StringPool.SLASH + + extLayout.getLayoutId(), MatchMode.ANYWHERE)); + criteria.addOrder(Order.asc("groupId")); + criteria.addOrder(org.hibernate.criterion.Order.asc("name")); + + DynamicQueryInitializer queryInitializer = new DynamicQueryInitializerImpl( + criteria); + List targets; + try { + targets = LayoutLocalServiceUtil.dynamicQuery(queryInitializer); + } catch (SystemException e) { + throw new RuntimeException(e); + } + + return targets; + } + +} Index: portal-impl/src/com/liferay/portal/events/HmServicePreAction.java =================================================================== --- portal-impl/src/com/liferay/portal/events/HmServicePreAction.java (revision 0) +++ portal-impl/src/com/liferay/portal/events/HmServicePreAction.java (revision 0) @@ -0,0 +1,104 @@ +/** + * + */ +package com.liferay.portal.events; + +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import com.liferay.portal.PortalException; +import com.liferay.portal.SystemException; +import com.liferay.portal.events.ServicePreAction; +import com.liferay.portal.model.Layout; +import com.liferay.portal.model.LayoutConstants; +import com.liferay.portal.model.User; +import com.liferay.portal.security.permission.PermissionChecker; +import com.liferay.portal.service.LayoutLocalServiceUtil; + +/** + * This class adds support for extensions points to the ServicePreAction class. + * Extension points allows to define specific layout pages in one community that + * are replaced by navigation branches of other communities. + * + * @author Olaf Fricke + * + */ +public class HmServicePreAction extends ServicePreAction { + + /** + * Calculates the viewable layouts. + *

+ * This method is used to perform the extension of communities at runtime. + * It consists of the following steps: + *