/*
* 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.db;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import COM.FutureTense.Interfaces.ICS;
import COM.FutureTense.Util.ftErrors;
import com.fatwire.assetapi.data.AssetId;
import com.fatwire.gst.foundation.CSRuntimeException;
import com.fatwire.gst.foundation.controller.AssetIdWithSite;
import com.fatwire.gst.foundation.facade.runtag.asset.FilterAssetsByDate;
import com.fatwire.gst.foundation.facade.sql.Row;
import com.fatwire.gst.foundation.facade.sql.SqlHelper;
import com.fatwire.gst.foundation.url.WraPathTranslationService;
import com.fatwire.gst.foundation.vwebroot.VirtualWebroot;
import com.fatwire.gst.foundation.vwebroot.VirtualWebrootApiBypassDao;
import com.fatwire.gst.foundation.vwebroot.VirtualWebrootDao;
import com.fatwire.gst.foundation.wra.SimpleWRADao;
import com.fatwire.gst.foundation.wra.SimpleWra;
import com.openmarket.xcelerate.asset.AssetIdImpl;
/**
* WraPathTranslationService that is backed by the GSTUrlRegistry table.
*
* @author Dolf Dijkstra
* @since Jun 17, 2010
*
* @deprecated as of release 12.x, replace with WCS 12c's native vanity URLs support.
*
*/
@Deprecated
public class UrlRegistry2 implements WraPathTranslationService {
private static final Logger LOG = LoggerFactory.getLogger("tools.gsf.legacy.url.db.UrlRegistry2");
private final ICS ics;
private final SimpleWRADao wraDao;
private final VirtualWebrootDao vwDao;
private final UrlRegistryDao regDao;
public UrlRegistry2(final ICS ics, final SimpleWRADao wraDao, final VirtualWebrootDao vwDao,
final UrlRegistryDao regDao) {
this.ics = ics;
this.wraDao = wraDao;
this.vwDao = vwDao;
this.regDao = regDao;
}
@Override
public AssetIdWithSite resolveAsset(final String virtual_webroot, final String url_path) {
for (final VanityUrl asset : regDao.resolveAsset(virtual_webroot, url_path)) {
final String assettype = asset.getAssettype();
final long assetid = asset.getAssetid();
final AssetIdWithSite id = new AssetIdWithSite(assettype, assetid, asset.getOpt_site());
if (FilterAssetsByDate.isValidOnDate(ics, id, null)) {
if (LOG.isDebugEnabled()) {
LOG.debug("Resolved and validated effective date for asset " + id + " from virtual-webroot:"
+ virtual_webroot + " and url-path:" + url_path);
}
return id;
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Resolved asset "
+ id
+ " but it is not valid on the effective date as determined by the asset.filterassetsbydate tag.");
}
}
}
return null;
}
@Override
public void addAsset(final AssetId id) {
if (LOG.isTraceEnabled()) {
LOG.trace("addAsset(AssetId) called for asset " + id);
}
updateAsset_(id);
}
@Override
public void updateAsset(final AssetId id) {
if (LOG.isTraceEnabled()) {
LOG.trace("updateAsset(AssetId) called for asset " + id);
}
updateAsset_(id);
}
@Override
public void deleteAsset(final AssetId id) {
if (LOG.isTraceEnabled()) {
LOG.trace("deleteAsset(AssetId) called for asset " + id);
}
regDao.delete(id);
}
private void addAsset_(final SimpleWra wra) {
final AssetId asset = wra.getId();
final VirtualWebroot vw = vwDao.lookupVirtualWebrootForUri(wra.getPath());
if (vw != null) {
final String site = wraDao.resolveSite(asset);
regDao.add(wra, vw, site);
} else {
if (LOG.isTraceEnabled()) {
LOG.trace("Did not add WRA " + asset + " to url registry because no valid virtual webroot was found");
}
}
}
private boolean compare(final Date d1, final Date d2) {
if (d1 == null && d2 == null) {
return true;
}
if (d1 == null && d2 != null) {
return false;
}
return d1.equals(d2);
}
private boolean compare(final VanityUrl url, final SimpleWra wra) {
// path, startdate && enddate all the same?
if (url == null) {
return false;
}
if (wra == null) {
return false;
// path cannot be null
}
if (wra.getPath().equals(url.getPath()) == false) {
return false;
}
if (compare(wra.getEndDate(), url.getEnddate()) == false) {
return false;
}
if (compare(wra.getStartDate(), url.getStartdate()) == false) {
return false;
}
return true;
}
public void updateAsset_(final AssetId id) {
/*
* here is the optimization question, what is faster, the select on the
* urlregtable or on the assettable? Probably it depends on number rows
* in table. If urlregtable is smaller than individual assettype table
* the lookup for registry table first is probably preferred. Otherwise,
* change to logic below to first lookup the wraDao.getWra().
*/
final SimpleWra wra = wraDao.getWra(id);
if (isWra(wra)) {
final VanityUrl row = regDao.read(id);
if (!compare(row, wra)) {
regDao.delete(id);
addAsset_(wra);
} else if (row == null) {
addAsset_(wra);
}
} else {
regDao.delete(id);
}
}
private boolean isWra(final SimpleWra wra) {
return wra != null && StringUtils.isNotBlank(wra.getPath()) && StringUtils.isNotBlank(wra.getTemplate());
}
/**
* Rebuild all entries in the GST URL Registry table. Uses brute force
* method and can take a very long time.
*
* @param stream stream a message back to the browser to prevent timeouts
*/
public void rebuild(boolean stream) {
if (!ics.UserIsMember("xceladmin")) {
throw new CSRuntimeException("xceladmin user required to rebuild URL Registry", ftErrors.noprivs);
}
regDao.clear();
if (stream)
ics.StreamText("Re-creating url registry entries for ");
for (String type : _lookupWraAssetTypes()) {
LOG.debug("Re-creating all registry entries for asset type " + type);
if (stream)
ics.StreamText("Asset type: " + type);
for (Row r : SqlHelper.select(ics, type, "SELECT id,template,path,startdate,enddate FROM " + type
+ " WHERE status!='VO' AND path IS NOT NULL and template IS NOT NULL")) {
long id = r.getLong("id");
AssetId aid = new AssetIdImpl(type, id);
SimpleWra wra = new SimpleWra(r, aid);
if (isWra(wra)) {
LOG.debug("Attempting to rebuild registry entry for " + aid);
// stream to prevent timeouts...???? :-(
if (stream)
ics.StreamText(" " + id); // stream immediately (don't
// use StreamEvalBytes)
addAsset_(wra);
}
}
}
if (stream)
ics.StreamText("...completed");
LOG.debug("Rebuild completed");
}
private final Collection<String> SYSTEM_TYPES = Arrays.asList("Template", "CSElement", "SiteEntry", "Collection",
"Page", "Query", "Link", "Dimension", "DimensionSet", "AttrTypes", "AdvCols", "Segments", "Promotions",
"ScalarVals", "HistoryVals", "HFields", "GSTFilter", "GSTAttribute", "GSTPDefinition", "GSTDefinition",
"GSTVirtualWebroot", "GSTProperty", "FW_View", "FW_Application");
private Collection<String> _lookupWraAssetTypes() {
Set<String> x = new HashSet<String>();
for (Row r : SqlHelper.select(ics, "AssetType", "select assettype from AssetType")) {
String type = r.getString("assettype");
if (!SYSTEM_TYPES.contains(type)) {
x.add(type); // TODO: be much smarter. Exclude flex definitions,
// parent devs, filters. Get fancy and exclude
// non-compliant definitions.
}
}
x.add("Page"); // yes, I know it's listed as a system asset type, but it's both system and WRA in 11g.
return x;
}
@Deprecated
public static UrlRegistry2 lookup(final ICS ics) {
LOG.trace("Entered UrlRegistry2.lookup...");
final Object o = ics.GetObj(UrlRegistry2.class.getName());
if (o instanceof UrlRegistry2) {
return (UrlRegistry2) o;
}
final UrlRegistry2 x = new UrlRegistry2(ics, new DbSimpleWRADao(ics), new VirtualWebrootApiBypassDao(ics),
new UrlRegistryDaoImpl(ics));
ics.SetObj(UrlRegistry2.class.getName(), x);
return x;
}
}