package org.opentides.service.impl; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.opentides.annotation.CrudSecure; import org.opentides.bean.UrlResponseObject; import org.opentides.bean.Widget; import org.opentides.bean.user.BaseUser; import org.opentides.dao.WidgetDao; import org.opentides.service.WidgetService; import org.opentides.util.SecurityUtil; import org.opentides.util.StringUtil; import org.opentides.util.UrlUtil; import org.opentides.util.WidgetUtil; import org.springframework.stereotype.Service; @Service("widgetService") public class WidgetServiceImpl extends BaseCrudServiceImpl<Widget> implements WidgetService { private static final Logger _log = Logger.getLogger(WidgetServiceImpl.class); private String widgetColumn; private String IPAddress; private static Pattern pattern = Pattern.compile("<img\\s[^>]*src=\"?(.*?)[\" ]", Pattern.CASE_INSENSITIVE|Pattern.MULTILINE); @Override public Widget findByName(String name) { Widget example = new Widget(); example.setName(name); List<Widget> dashboardList = getDao().findByExample(example, true); if (dashboardList != null && dashboardList.size() > 0) { return dashboardList.get(0); } return null; } @Override public Widget findByUrl(String url) { Widget example = new Widget(); example.setUrl(url); List<Widget> dashboardList = getDao().findByExample(example, true); if (dashboardList != null && dashboardList.size() > 0) { return dashboardList.get(0); } return null; } @Override public List<Widget> getCurrentUserWidgets() { Widget example = new Widget(); example.setIsUserDefined(true); List<Widget> widgets = new ArrayList<Widget>(); for (Widget widget:findByExample(example, true)) { if (StringUtil.isEmpty(widget.getAccessCode())) { widgets.add(widget); } else if (SecurityUtil.currentUserHasPermission(widget.getAccessCode())) { widgets.add(widget); } } return widgets; } @Override public Widget requestWidget(String widgetUrl, String name, HttpServletRequest req) { Widget widget = findByName(name); if (widget != null) { long now = System.currentTimeMillis(); Date lastCacheDate = widget.getLastCacheUpdate(); boolean useCache = false; // check if we should use cache or not if (lastCacheDate != null) { long expire = widget.getLastCacheUpdate().getTime() + widget.getCacheDuration() * 1000; if (widget.getCacheType().startsWith( Widget.TYPE_IMAGE) || now < expire) useCache = true; } if (useCache) { _log.debug("Reusing widget [" + widget.getName() + "] from cache..."); // retrieve from cache return widget; } else { // retrieve from url String url = widget.getUrl(); if (!UrlUtil.hasProtocol(url)) { String slash = "/"; if (!url.startsWith("/")) { url = slash + url; } url = req.getContextPath().toString() + url; if (req.getServerPort() != 80) { url = ":" + Integer.toString(req.getServerPort()) + url; } url = UrlUtil.ensureProtocol(req.getServerName() + url); } // set the IP Address as param Map<String, Object> param = new HashMap<String, Object>(); if (StringUtil.isEmpty(IPAddress)) param.put("IPAddress", IPAddress); UrlResponseObject response = WidgetUtil.getPage(url, req, param); if (response==null) return null; if (response.getResponseType() .startsWith(Widget.TYPE_IMAGE)) { _log.debug("Retrieving image [" + widget.getName() + "] from url [" + widget.getUrl() + "]..."); widget.setCacheType(response.getResponseType()); widget.setCache(response.getResponseBody()); widget.setLastCacheUpdate(new Date()); save(widget); _log.debug("Saved image [" + widget.getName() + "] to cache..."); return widget; } else { _log.debug("Retrieving widget [" + widget.getName() + "] from url [" + widget.getUrl() + "]..."); widget.setCacheType(response.getResponseType()); // check for image inside the html String html = new String(response.getResponseBody()); String hostname = UrlUtil.getHostname(url); Matcher matcher = pattern.matcher(html); while (matcher.find()) { // add image link to cache String imageUrl = matcher.group(1); String cacheUrl = imageUrl; if (!UrlUtil.hasProtocol(cacheUrl)) { if (!imageUrl.startsWith("/")) { cacheUrl = "http://" + hostname + "/" + imageUrl; } else { cacheUrl = "http://" + hostname + imageUrl; } } String imageName = this.addCache(cacheUrl, req, widget); // replace html that reference to image with cached image String newUrl = widgetUrl+"?name="+imageName; html = html.replace(imageUrl, newUrl); } widget.setCache(html.getBytes()); widget.setLastCacheUpdate(new Date()); save(widget); _log.debug("Saved widget [" + widget.getName() + "] to cache..."); return widget; } } } return null; } @Override public int getColumnConfig() { return StringUtil.convertToInt(getWidgetColumn(),2); } @Override public List<Widget> findDefaultWidget(BaseUser user) { return ((WidgetDao) getDao()).findDefaultWidget(user); } @Override public List<Widget> findWidgetWithAccessCode(List<String> accessCodes) { return ((WidgetDao) getDao()).findWidgetWithAccessCode(accessCodes); } public void setIPAddress(String iPAddress) { IPAddress = iPAddress; } public String getWidgetColumn() { return widgetColumn; } public void setWidgetColumn(String widgetColumn) { this.widgetColumn = widgetColumn; } /** * Private helper to save image cache. * * @param imageUrl * @return */ private String addCache(String url, HttpServletRequest req, Widget parentSettings) { Widget settings = this.findByUrl(url); if (settings == null) settings = new Widget(url, parentSettings); UrlResponseObject response = WidgetUtil.getPage(url, req, null); if (response.getResponseType().startsWith(Widget.TYPE_IMAGE)) settings.setCacheType(Widget.TYPE_IMAGE); else settings.setCacheType(Widget.TYPE_HTML); settings.setCache(response.getResponseBody()); this.save(settings); settings.setName(""+settings.getId()); this.save(settings); return settings.getName(); } }