/* * Copyright 2010 FatWire Corporation. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.fatwire.gst.foundation.url; import java.util.Map; import COM.FutureTense.Export.Reference; import COM.FutureTense.Export.ReferenceException; import COM.FutureTense.Interfaces.ICS; import COM.FutureTense.Interfaces.IReference; import COM.FutureTense.Util.ftMessage; import com.fatwire.assetapi.data.AssetId; import com.fatwire.cs.core.uri.Definition; import com.fatwire.gst.foundation.vwebroot.AssetApiVirtualWebrootDao; import com.fatwire.gst.foundation.vwebroot.VirtualWebroot; import com.fatwire.gst.foundation.wra.AssetApiWraCoreFieldDao; import com.fatwire.gst.foundation.wra.VanityAsset; import com.fatwire.gst.foundation.wra.WraCoreFieldDao; import com.openmarket.xcelerate.asset.AssetIdImpl; import com.openmarket.xcelerate.publish.PageRef; import com.openmarket.xcelerate.publish.PubConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static COM.FutureTense.Interfaces.Utilities.goodString; /** * This is the WebReferenceable assets PageRef class. This overrides the default * PageRef, so we can manipulate the arguments that go into the assembler while * we have database access. * * <p> * It will alter the input args map by adding the derived parameters * <ul> * <li>virtual-webroot</li> * <li>url-path</li> * <li>pagename</li> * </ul> * to the map before calling super.setParameters(args, ics). * <p> * This modification is ONLY done when * <ol> * <li>the satellite context is Satellite</li> * <li>the app type is Content Server</li> * <li>the environment name is set</li> * <li>the asset is found</li> * <li>the asset has a path set</li> * <li>a virtual webroot can be found for the path set and environment name</li> * </ol> * * <ol> * <li>PageRef extends Reference implements IPageRef</li> * <li>Reference implements IReference</li> * <li>interface IPageRef extends IReference</li> * <li>interface IReference extends Definition</li> * </ol> * * * @author Dolf Dijkstra * @author Tony Field * @see Reference * @see IReference * @see Definition * @since Jun 17, 2010 * * * @deprecated as of release 12.x, replace with WCS 12c's native vanity URLs support. * */ public class WraPageReference extends PageRef { /** * This logic is quite specific to the GSF so create a dedicated logger. */ private static final Logger log = LoggerFactory.getLogger("tools.gsf.legacy.url.WraPageReference"); public static final String GST_DISPATCHER = "GST/Dispatcher"; /* * (non-Javadoc) * * @see * com.openmarket.xcelerate.publish.PageRef#setParameters(java.util.Map, * COM.FutureTense.Interfaces.ICS) */ @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public void setParameters(Map args, ICS ics) throws ReferenceException { if (doVanityUrl(args, ics)) { VanityUrlCalculationContext ctx = getVanityUrlCalculationContext(args, ics, requireWraForVanityUrls()); VirtualWebroot vw = ctx.getVirtualWebrootForAsset(args, ics); args.put("virtual-webroot", vw.getEnvironmentVirtualWebroot()); args.put("url-path", ctx.getVanityAsset(args, ics).getPath().substring(vw.getMasterVirtualWebroot().length())); // has pagename been set? if not, use default. String pagename = ics.GetProperty(WraPathAssembler.DISPATCHER_PROPNAME, "ServletRequest.properties", true); if (!goodString(pagename)) { pagename = GST_DISPATCHER; } // pagename or wrapperpage depending on whether or not we're going to use a wrapper. if (args.get(PubConstants.WRAPPERPAGE) != null) args.put(PubConstants.WRAPPERPAGE, pagename); else args.put("pagename", pagename); } super.setParameters(args, ics); } /** * Method specifying whether or not vanity URLs are allowed for assets that are just Vanity assets or that have to * be full WRA assets. This is provided for backward compatibility. Previously, only WRA assets could have * vanity URLs, but the requirement has been loosened substantially. * @return true for backward-compatibility - meaning that only WRA assets can have vanity URLs. False if vanity * URLs can be assigned to non-WRAs. */ protected boolean requireWraForVanityUrls() { return true; } /** * Determine if we should look up the virtual webroot and url path or not */ private boolean doVanityUrl(Map args, ICS ics) { if (log.isDebugEnabled()) { log.debug("checking to see if the URL for this asset should be a vanity url. asset: "+args.get("c")+":"+args.get("cid")); } if (getSatelliteContext() != SatelliteContext.SATELLITE_SERVER) { log.debug("not applying vanity URL because satellite context is not satellite"); return false; } if (!VanityUrlCalculationContext.isGetTemplateUrl(args, ics)) { log.debug("not applying vanity URL because API usage was not found to be the gettemplateurl tag"); return false; } VanityUrlCalculationContext ctx = getVanityUrlCalculationContext(args, ics, requireWraForVanityUrls()); if (!ctx.isGsfEnvironmentSet(args, ics)) { log.debug("not applying vanity URL because virtual webroot environment is not set"); return false; } if (!ctx.isVanityAsset(args, ics)) { if (requireWraForVanityUrls()) log.debug("not applying vanityURL because asset is not a WRA"); else log.debug("not applying vanityURL because asset is not a Vanity Asset"); return false; } if (!ctx.hasVirtualWebroot(args, ics)) { log.debug("not applying vanity URL because we could not find a valid virtual webroot in the asset's path field"); return false; } log.debug("Asset passed tests and a vanity URL will be created"); return true; } /** * Figuring out whether or not we should do vanity URL validation is expensive. Optimize the process as much * as possible * @param args input params * @param ics ics context * @param requireWraForVanity true to enforce having a WRA for a vanity URL, false to allow just a vanity asset. * @return calcualtion context, containing pointers to heavy objects */ private VanityUrlCalculationContext getVanityUrlCalculationContext(Map args, ICS ics, boolean requireWraForVanity) { String c = (String) args.get("c"); String cid = (String) args.get("cid"); String key = "gsf:vanityUrlCalculationContext:"+c+":"+cid; Object o = ics.GetObj(key); if (o == null) { o = new VanityUrlCalculationContext(c, cid, requireWraForVanity); ics.SetObj(key, o); } return (VanityUrlCalculationContext) o; } /** * Handy context object, which holds expensive objects required when determining if * a vanity URL should be created for an asset, and when actually calculating it. */ private static class VanityUrlCalculationContext { private final boolean requireWraFields; private final AssetId assetId; private AssetApiVirtualWebrootDao assetApiVirtualWebrootDao; private WraCoreFieldDao wraCoreFieldDao; boolean checkedForEnvironment = false; private String currentEnvironment; boolean checkedForWebroot = false; VirtualWebroot virtualWebrootForAsset; boolean checkedForVanitySupport = false; VanityAsset vanityAsset; VanityUrlCalculationContext(String c, String cid, boolean requireWraFields) { this.requireWraFields = requireWraFields; assetId = new AssetIdImpl(c, Long.parseLong(cid)); } private AssetApiVirtualWebrootDao getAssetApiVirtualWebrootDao(Map args, ICS ics) { if (assetApiVirtualWebrootDao == null) { assetApiVirtualWebrootDao = new AssetApiVirtualWebrootDao(ics); } return assetApiVirtualWebrootDao; } private WraCoreFieldDao getWraCoreFieldDao(Map args, ICS ics) { if (wraCoreFieldDao == null) { wraCoreFieldDao = new AssetApiWraCoreFieldDao(ics); } return wraCoreFieldDao; } private boolean isVanityAsset(Map args, ICS ics) { WraCoreFieldDao dao = getWraCoreFieldDao(args, ics); return requireWraFields ? dao.isWebReferenceable(assetId) : dao.isVanityAsset(assetId); } private boolean isGsfEnvironmentSet(Map args, ICS ics) { return getCurrentEnvironment(args, ics) != null; } private String getCurrentEnvironment(Map args, ICS ics) { if (currentEnvironment == null && checkedForEnvironment == false) { currentEnvironment = getAssetApiVirtualWebrootDao(args, ics).getVirtualWebrootEnvironment(); checkedForEnvironment = true; } return currentEnvironment; } private VanityAsset getVanityAsset(Map args, ICS ics) { if (vanityAsset == null && checkedForVanitySupport == false) { WraCoreFieldDao dao = getWraCoreFieldDao(args, ics); vanityAsset = requireWraFields ? dao.getWra(assetId) : dao.getVanityWra(assetId); checkedForVanitySupport = true; } return vanityAsset; } private boolean hasVirtualWebroot(Map args, ICS ics) { return getVirtualWebrootForAsset(args, ics) != null; } private VirtualWebroot getVirtualWebrootForAsset(Map args, ICS ics) { if (virtualWebrootForAsset == null && checkedForWebroot == false) { AssetApiVirtualWebrootDao vwdao = getAssetApiVirtualWebrootDao(args, ics); VanityAsset v = getVanityAsset(args, ics); virtualWebrootForAsset = vwdao.lookupVirtualWebrootForAsset(v); checkedForWebroot = true; } return virtualWebrootForAsset; } /** * Check to see if the tag being called is a getTemplateUrl tag. If it is * not, we should not be processing this for special links. Note it's not * that easy to figure this out, and there could be missing pieces here. * * @param args tag args * @return true if it's a gettemplateurl tag, false otherwise. */ private static boolean isGetTemplateUrl(Map args, ICS ics) { if (args.get("c") == null) return false; if (args.get("cid") == null) return false; String pagename = (String)args.get(ftMessage.PageName); if (pagename == null) return false; if (pagename.split("/").length < 2) return false; // need site/type/tname or site/tname at least for a valid URL if (args.get(PubConstants.WRAPPERPAGE) != null) return true; // wrapper is only supported for GTU calls else { // possible further checks here just in case } return true; } } }