View Javadoc
1   /*
2    * Copyright 2011 FatWire Corporation. All Rights Reserved.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package tools.gsf.mapping;
17  
18  import COM.FutureTense.Interfaces.ICS;
19  import COM.FutureTense.Interfaces.Utilities;
20  import com.fatwire.cs.core.db.PreparedStmt;
21  import com.fatwire.cs.core.db.StatementParam;
22  import org.apache.commons.lang3.StringUtils;
23  import org.slf4j.Logger;
24  import org.slf4j.LoggerFactory;
25  
26  import tools.gsf.facade.assetapi.AssetAccessTemplate;
27  import tools.gsf.facade.assetapi.AssetIdWithSite;
28  import tools.gsf.facade.sql.Row;
29  import tools.gsf.facade.sql.SqlHelper;
30  
31  import java.util.Arrays;
32  import java.util.Collections;
33  import java.util.HashMap;
34  import java.util.Map;
35  
36  /**
37   * MappingService implementation making use to sql queries to perform fast lookup of mapping values.
38   *
39   * @author Dolf Dijkstra
40   * @author Tony Field
41   * @since Apr 13, 2011
42   */
43  public final class IcsMappingService implements MappingService {
44  	
45  	private static final Logger LOG = LoggerFactory.getLogger(IcsMappingService.class);
46  
47      private final static PreparedStmt template = new PreparedStmt("SELECT * FROM Template_Map WHERE cs_ownerid=? AND cs_siteid=?",
48              Arrays.asList("Template", "Template_Map"));
49      private final static PreparedStmt element = new PreparedStmt("SELECT * FROM CSElement_Map WHERE cs_ownerid=? AND cs_siteid=?",
50              Arrays.asList("CSElement", "CSElement_Map"));
51      private static final PreparedStmt lookup_sitecatalog = new PreparedStmt("select * from SiteCatalog where pagename = ?",
52              Arrays.asList("SiteEntry","Template")); // we will only query pagenames that map to these, we promise... we use SiteEntry and Template instead of SiteCatalog to avoid security blocking the query
53      private static final PreparedStmt lookup_template = new PreparedStmt("select * from Template where rootelement = ?",
54              Collections.singletonList("Template")); // we will only query pagenames that map to these, we promise
55      private static final PreparedStmt lookup_cselement = new PreparedStmt("select * from CSElement where rootelement = ?",
56              Collections.singletonList("CSElement")); // we will only query pagenames that map to these, we promise
57      static {
58          template.setElement(0, "Template_Map", "cs_ownerid");
59          template.setElement(1, "Template_Map", "cs_siteid");
60          element.setElement(0, "CSElement_Map", "cs_ownerid");
61          element.setElement(1, "CSElement_Map", "cs_siteid");
62          lookup_sitecatalog.setElement(0, "SiteEntry", "pagename"); // Using SiteEntry instead of SiteCatalog so to avoid security blocking the query
63          lookup_template.setElement(0, "Template", "rootelement");
64          lookup_cselement.setElement(0, "CSElement", "rootelement");
65      }
66  
67      private final ICS ics;
68      private final AssetAccessTemplate aat;
69  
70      /**
71       * @param ics Content Server context object
72       * @param aat AssetAccessTemplate object 
73       */
74      public IcsMappingService(final ICS ics, final AssetAccessTemplate aat) {
75          this.ics = ics;
76          this.aat = aat;
77      }
78  
79      public Map<String, MappingValue> readMapping(final AssetIdWithSite id) {
80          if ("Template".equals(id.getType())) {
81              return readIt(id, template);
82          } else if ("CSElement".equals(id.getType())) {
83              return readIt(id, element);
84          } else {
85              throw new IllegalArgumentException("Cannot handle " + id.getType());
86          }
87  
88      }
89  
90      private Map<String, MappingValue> readIt(final AssetIdWithSite id, final PreparedStmt stmt) {
91          final StatementParam param = stmt.newParam();
92          param.setLong(0, id.getId());
93          param.setLong(1, aat.readSiteInfo(id.getSite()).getId());
94          final Map<String, MappingValue> map = new HashMap<>();
95          for (final Row row : SqlHelper.select(ics, stmt, param)) {
96              final String key = row.getString("cs_key");
97  
98              final MappingValue k = new MappingValue(MappingValue.Type.valueOf(row.getString("cs_type").toLowerCase()),
99                      row.getString("cs_value"));
100             map.put(key, k);
101         }
102         return map;
103     }
104 
105     @Override
106     public AssetIdWithSite resolveMapped(String eid, String tid, String site) {
107         if (site != null) {
108             if (eid != null) {
109                 return new AssetIdWithSite("CSElement", Long.valueOf(eid), site);
110             }
111             if (tid != null) {
112                 return new AssetIdWithSite("Template", Long.valueOf(tid), site);
113             }
114         }
115         return null;
116     }
117 
118     @Override
119     public AssetIdWithSite resolveMapped(String pagename) {
120         // note: we can only map templates or CSElements that are rootelements of pages. We cannot resolve
121         // the mapped code in other cases unfortunately.
122         MappingPageData pageData = readPageData(pagename);
123         if (pageData.isSiteEntry()) {
124         	LOG.debug("PageData is SiteEntry");
125             long eid = lookupCSElement(pageData.rootelement);
126             if (LOG.isDebugEnabled()) {
127             	LOG.debug("Looked up eid for rootelement '" + pageData.rootelement + "', got: " + eid);
128             }
129             if (eid > -1) {
130                 String site = ics.GetVar("site");
131                 LOG.debug("site = " + site);
132                 if (StringUtils.isBlank(site)) {
133                 	LOG.debug("Cannot find site... will attempt extracting it from resargs");
134                     site = pageData.getSiteResarg();
135                     LOG.debug("site = " + site);
136                 }
137                 if (StringUtils.isNotBlank(site)) {
138                     return new AssetIdWithSite("CSElement", eid, site);
139                 }
140             }
141         } else {
142         	LOG.debug("PageData not a SiteEntry... assuming Template");
143             long tid = lookupTemplate(pageData.rootelement);
144             if (LOG.isDebugEnabled()) {
145             	LOG.debug("Looked up tid for rootelement '" + pageData.rootelement + "', got: " + tid);
146             }
147             if (tid > 0) {
148                 String site = ics.GetVar("site");
149                 LOG.debug("site = " + site);
150                 if (StringUtils.isBlank(site)) {
151                 	if (LOG.isDebugEnabled()) {
152                 		LOG.debug("Will look up site for (pressumed) template...");
153                 	}
154                     site = lookupSiteForTemplate(pageData);
155                     LOG.debug("site = " + site);
156                 }
157                 if (StringUtils.isNotBlank(site)) {
158                     return new AssetIdWithSite("Template", tid, site);
159                 }
160             }
161         }
162 
163         LOG.debug("Cannot determine asset ID (CSElement eid / Template tid) from pagename '" + pagename + "'");
164         
165         return null;
166     }
167 
168     private MappingPageData readPageData(String pagename) {
169         StatementParam param = lookup_sitecatalog.newParam();
170         param.setString(0, pagename);
171         Row row = SqlHelper.selectSingle(ics, lookup_sitecatalog, param);
172         return new MappingPageData(row);
173     }
174 
175     private long lookupCSElement(String rootelement) {
176         StatementParam param = lookup_cselement.newParam();
177         param.setString(0, rootelement);
178         Row row = SqlHelper.selectSingle(ics, lookup_cselement, param);
179         return row == null ? -1L : row.getLong("id");
180     }
181 
182     private long lookupTemplate(String rootelement) {
183         StatementParam param = lookup_template.newParam();
184         param.setString(0, rootelement);
185         Row row = SqlHelper.selectSingle(ics, lookup_template, param);
186         return row == null ? -1L : row.getLong("id");
187     }
188 
189     private String lookupSiteForTemplate(MappingPageData pageData) {
190         // always siteName/type/tname or siteName/tname
191         return StringUtils.substringBefore(pageData.pagename, "/");
192     }
193 
194     private static class MappingPageData {
195         private final String pagename;
196         private final Map<String,String> resargs;
197         private final String rootelement;
198         // could add more here if we cared but this is a private class so no need to worry now
199 
200         private MappingPageData(Row row) {
201             this.pagename = row.getString("pagename");
202             this.resargs = new HashMap<>();
203             Utilities.getParams(row.getString("resargs1"), resargs, false);
204             Utilities.getParams(row.getString("resargs2"), resargs, false);
205             this.rootelement = row.getString("rootelement");
206         }
207 
208         private boolean isSiteEntry() {
209             return resargs.containsKey("seid");
210         }
211 
212         private String getSiteResarg() {
213             return resargs.get("site");
214         }
215     }
216 }