
com.day.cq.analytics.sitecatalyst.ImpressionsImporter Maven / Gradle / Ivy
/*************************************************************************
*
* ADOBE CONFIDENTIAL
* __________________
*
* Copyright 2011 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and may be covered by U.S. and Foreign Patents,
* patents in process, and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
**************************************************************************/
package com.day.cq.analytics.sitecatalyst;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Dictionary;
import java.util.Set;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.apache.sling.commons.osgi.OsgiUtil;
import org.apache.sling.discovery.TopologyEvent;
import org.apache.sling.discovery.TopologyEventListener;
import org.apache.sling.settings.SlingSettingsService;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.day.cq.commons.inherit.HierarchyNodeInheritanceValueMap;
import com.day.cq.commons.inherit.InheritanceValueMap;
import com.day.cq.polling.importer.ImportException;
import com.day.cq.polling.importer.Importer;
import com.day.cq.statistics.StatisticsService;
import com.day.cq.wcm.webservicesupport.Configuration;
import com.day.cq.wcm.webservicesupport.ConfigurationManager;
import com.day.cq.wcm.webservicesupport.ConfigurationManagerFactory;
/**
* The ImpressionsImporter
is a {@link Importer} for importing page
* impressions from SiteCatalyst.
*
* Page impressions are only fetched if the configured
* ImpresionsImporter.REPORT_INTERVAL is larger than the time since the last
* page impressions import. A timestamp for the last import attempt will be
* stored in a cq:lastAttempt
property of the cq:PollConfig parent
* resource
*
*
* @deprecated Functionality has been replaced by the generic service Adobe AEM Analytics Report Importer
*/
@Component(
metatype = true,
label = "Day CQ Analytics SiteCatalyst Impressions Importer",
description = "Imports SiteCatalyst Page Impressions periodically into CQ"
)
@Service
@Properties(value = {
@org.apache.felix.scr.annotations.Property(name = Importer.SCHEME_PROPERTY, value = "sitecatalyst", propertyPrivate = true)
})
@Deprecated
public class ImpressionsImporter implements Importer, TopologyEventListener {
/** default log */
private final Logger log = LoggerFactory.getLogger(getClass());
@Property(
label = "Import interval",
description = "Import interval in milliseconds. Default is set to 43200000 (12h).",
longValue=43200000
)
protected static final String REPORT_INTERVAL = "cq.analytics.sitecatalyst.importer.inverval";
private static final long DEFAULT_INTERVAL = 43200000L;
private long reportInterval;
@Property(
label = "Enabled",
description = "Indicator if importer is enabled or disabled.",
boolValue = true
)
private static final String ENABLED = "cq.analytics.sitecatalyst.importer.enabled";
private static final boolean DEFAULT_ENABLED = false;
private boolean enabled;
@Reference
private SlingSettingsService settingsService;
@Reference
private SitecatalystWebservice webservice;
@Reference
private StatisticsService statService;
@Reference
private ConfigurationManagerFactory cfgManagerFactory;
/** Leader flag */
private boolean isLeader = false;
/*
* (non-Javadoc)
* @see com.day.cq.polling.importer.Importer#importData(java.lang.String, java.lang.String, org.apache.sling.api.resource.Resource)
*/
public void importData(String scheme, String dataSource, Resource target)
throws ImportException {
if (enabled) {
if (!isLeader) {
log.info("Import skipped on slave instance");
return;
}
try {
Resource pageResource = target.getParent().getParent();
InheritanceValueMap pageProperties = new HierarchyNodeInheritanceValueMap(pageResource);
Node analytics = target.getParent().adaptTo(Node.class);
String lastAttempt = "0";
if (analytics.hasProperty("cq:lastAttempt")) {
lastAttempt = analytics.getProperty("cq:lastAttempt").getString();
}
Configuration configuration = null;
String[] services = pageProperties.getInherited("cq:cloudserviceconfigs", new String[]{});
ConfigurationManager cfgManager = cfgManagerFactory.getConfigurationManager(target.getResourceResolver());
if (services.length > 0) {
configuration = cfgManager.getConfiguration("sitecatalyst", services);
}
if (configuration == null) {
log.error("SiteCatalyst configuration not found");
return;
}
if (isImporterDisabledFromConfig(configuration)) {
return;
}
String reportSuiteID = SitecatalystUtil.getReportSuites(settingsService, configuration);
if (lastAttempt.startsWith("waiting")) {
// try to read the triggered report
String reportID = lastAttempt.replace("waiting-", "");
try {
// call web service to get report status
String response = webservice.getReport(configuration, reportID);
JSONObject jsonObj = new JSONObject(response);
JSONObject report = jsonObj.optJSONObject("report");
if (report != null) {
JSONArray data = report.getJSONArray("data");
String lastAttemptDate = analytics.getProperty("cq:lastAttemptDate").getString();
String statsBasePath = "/var/statistics/pages" + analytics.getPath().replace("/jcr:content/analytics", "");
log.info("Report contains data items: " + data.length());
for (int i=0; i < data.length(); i++) { // iterate over the pages with data
JSONObject pageData = data.getJSONObject(i);
// update data for one page
this.setStatsData(statsBasePath, lastAttemptDate, pageData.getString("name"),
pageData.getJSONArray("counts").getString(0), target.getResourceResolver(), statService);
}
log.info("Report " + reportID + " imported");
} else {
Long errorId = jsonObj.optLong("error");
String errorMsg = jsonObj.optString("error_description");
log.warn("Report " + reportID + " failed due to (error:" + errorId + "): " + errorMsg);
}
} catch (SitecatalystException e) {
log.error("Call to Sitecatalyst failed", e);
} catch (JSONException e) {
log.error("Parsing JSON response failed", e);
} finally {
if (analytics.getSession().hasPendingChanges()) {
analytics.setProperty("cq:lastAttempt", Long.toString(System.currentTimeMillis()));
analytics.getSession().save();
}
}
} else {
// check whether a new report should be triggered
long last = Long.parseLong(lastAttempt);
if (last + reportInterval < System.currentTimeMillis()) { // last report is 'reportInterval' ago, trigger a new one
if (reportSuiteID == null) {
log.warn("cannot import data since no valid report suite ID was found");
return;
}
try {
String date;// = "2010-12-01";
// use the date from yesterday
Calendar cal = Calendar.getInstance();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
cal.add(Calendar.DATE, -1);
date = dateFormat.format(cal.getTime());
String response = webservice.queuePageViewReport(configuration, reportSuiteID, date);
JSONObject jsonObj = new JSONObject(response);
Long reportID = jsonObj.optLong("reportID");
if (reportID != 0) {
analytics.setProperty("cq:lastAttempt", "waiting-" + reportID);
analytics.setProperty("cq:lastAttemptDate", date);
log.info("Report queued: " + reportID + " for " + reportSuiteID + " and " + date);
} else {
Long errorId = jsonObj.optLong("error");
String errorMsg = jsonObj.optString("error_description");
log.warn(jsonObj.toString());
log.warn("queueing report failed due to (error:" + errorId + "): " + errorMsg);
analytics.setProperty("cq:lastAttempt", Long.toString(System.currentTimeMillis()));
}
} catch (SitecatalystException e) {
log.error("Call to SiteCatalyst failed", e);
analytics.setProperty("cq:lastAttempt", Long.toString(System.currentTimeMillis()));
} catch (JSONException e) {
log.error("Parsing JSON response failed", e);
analytics.setProperty("cq:lastAttempt", Long.toString(System.currentTimeMillis()));
} finally {
if (analytics.getSession().hasPendingChanges()) {
analytics.getSession().save();
}
}
}
}
} catch (PathNotFoundException e) {
log.error("Reading analytics data failed for " + target.getPath(), e);
} catch (RepositoryException e) {
log.error("Reading analytics data failed", e);
}
}
}
private void setStatsData(String basePath, String date, String name, String count, ResourceResolver resolver, StatisticsService statService) {
String statsPath = basePath;
if (!name.equals("home")) {
name = "/" + name.replace(":", "/");
} else {
name = "";
}
statsPath += name + "/.stats/";
statsPath += date.replace("-", "/");
Resource dayStats = resolver.getResource(statsPath);
if (dayStats!=null) { // already added stats for this day
ValueMap statsConfig = dayStats.adaptTo(ValueMap.class);
long views = statsConfig.get("views", Long.class);
if (views == Long.parseLong(count)) {
return;
}
}
// create new stats node or update existing one
ImpressionsEntry view = new ImpressionsEntry(basePath, name, date, Long.parseLong(count));
try {
statService.addEntry(view);
} catch (RepositoryException e) {
log.error("adding stats entry failed", e);
}
}
/**
* Check if the given Analytics cloud configuration is set to disable the impressions importer for the running instance mode.
*
* @param config the Analytics configuration to be checked
* @return {@code true} if the impressions importer is disabled for the running instance mode, {@code false} otherwise
*/
private boolean isImporterDisabledFromConfig(Configuration config) {
boolean disableAuthor = config.getInherited("disableImportPageImpressionsAuthor", false);
boolean disablePublish = config.getInherited("disableImportPageImpressionsPublish", false);
Set runmodes = settingsService.getRunModes();
if (disableAuthor && runmodes.contains("author")) {
return true;
}
if (disablePublish && runmodes.contains("publish")) {
return true;
}
return false;
}
// ----< SCR Integration >--------------------------------------------------
protected void activate(ComponentContext componentContext) {
@SuppressWarnings("unchecked")
final Dictionary config = componentContext.getProperties();
reportInterval = OsgiUtil.toLong(config.get(REPORT_INTERVAL), DEFAULT_INTERVAL);
enabled = OsgiUtil.toBoolean(config.get(ENABLED), DEFAULT_ENABLED);
}
/**
* @see org.apache.sling.discovery.TopologyEventListener#handleTopologyEvent(org.apache.sling.discovery.TopologyEvent)
*/
public void handleTopologyEvent(final TopologyEvent event) {
if (event.getType() == TopologyEvent.Type.TOPOLOGY_CHANGED
|| event.getType() == TopologyEvent.Type.PROPERTIES_CHANGED
|| event.getType() == TopologyEvent.Type.TOPOLOGY_INIT) {
this.isLeader = event.getNewView().getLocalInstance().isLeader();
} else if (event.getType() == TopologyEvent.Type.TOPOLOGY_CHANGING) {
this.isLeader = false;
}
}
// only here for backwards compatibility since this class is exported
protected void bindCfgManager(ConfigurationManager cfg) {
throw new UnsupportedOperationException();
}
// only here for backwards compatibility since this class is exported
protected void unbindCfgManager(ConfigurationManager cfg) {
throw new UnsupportedOperationException();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy