/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/web/trunk/web-impl/impl/src/java/org/sakaiproject/web/impl/WebServiceImpl.java$
* $Id: WebServiceImpl.java 39315 2007-12-15 18:08:26Z cwen@iupui.edu $
***********************************************************************************
*
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 The Sakai Foundation
*
* Licensed under the Educational Community 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.opensource.org/licenses/ECL-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 org.sakaiproject.web.impl;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.Vector;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.entity.api.Entity;
import org.sakaiproject.entity.api.EntityTransferrer;
import org.sakaiproject.entity.api.HttpAccess;
import org.sakaiproject.entity.api.Reference;
import org.sakaiproject.entity.api.ResourceProperties;
import org.sakaiproject.entity.cover.EntityManager;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.api.SitePage;
import org.sakaiproject.site.api.ToolConfiguration;
import org.sakaiproject.tool.api.Tool;
import org.sakaiproject.tool.api.ToolSession;
import org.sakaiproject.tool.cover.SessionManager;
import org.sakaiproject.tool.cover.ToolManager;
import org.sakaiproject.site.cover.SiteService;
import org.sakaiproject.web.api.WebService;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class WebServiceImpl implements WebService, EntityTransferrer
{
private static Log M_log = LogFactory.getLog(WebServiceImpl.class);
private static final String TOOL_ID = "sakai.iframe";
private static final String WEB_CONTENT = "web_content";
private static final String REDIRECT_TAB = "redirect_tab";
private static final String WEB_CONTENT_TITLE = "title";
private static final String WEB_CONTENT_URL = "url";
private static final String PAGE_TITLE = "page_title";
private static final String NEW_WINDOW = "open_in_new_window";
private static final String ARCHIVE_VERSION = "2.4"; // in case new features are added in future exports
private static final String VERSION_ATTR = "version";
private static final String WEB_CONTENT_URL_PROP = "source";
private static final String HEIGHT_PROP = "height";
private static final String SPECIAL_PROP = "special";
public static final String ATTR_TOP_REFRESH = "sakai.vppa.top.refresh";
public void init()
{
M_log.debug("init()");
// register as an entity producer
EntityManager.registerEntityProducer(this, REFERENCE_ROOT);
} // init
public String archive(String siteId, Document doc, Stack stack, String archivePath, List attachments)
{
StringBuilder results = new StringBuilder();
Base64 codec = new Base64();
try
{
int count = 0;
results.append("archiving " + getLabel() + " context "
+ Entity.SEPARATOR + siteId + Entity.SEPARATOR
+ SiteService.MAIN_CONTAINER + ".\n");
// start with an element with our very own (service) name
Element element = doc.createElement(SERVICE_NAME);
element.setAttribute(VERSION_ATTR, ARCHIVE_VERSION);
((Element) stack.peek()).appendChild(element);
stack.push(element);
if (siteId != null && siteId.trim().length() > 0)
{
Element webContentEl = doc.createElement(WEB_CONTENT);
Site site = SiteService.getSite(siteId);
List sitePages = site.getPages();
if (sitePages != null && !sitePages.isEmpty()) {
Iterator pageIter = sitePages.iterator();
while (pageIter.hasNext()) {
SitePage currPage = (SitePage) pageIter.next();
List toolList = currPage.getTools();
Iterator toolIter = toolList.iterator();
while (toolIter.hasNext()) {
ToolConfiguration toolConfig = (ToolConfiguration)toolIter.next();
// we do not want to archive "special" uses of sakai.iframe, such as worksite info
String special = toolConfig.getPlacementConfig().getProperty(SPECIAL_PROP);
if (toolConfig.getToolId().equals(TOOL_ID) && special == null) {
Element webContentData = doc.createElement(REDIRECT_TAB);
count++;
String contentUrl = toolConfig.getPlacementConfig().getProperty(WEB_CONTENT_URL_PROP);
String toolTitle = toolConfig.getTitle();
String pageTitle = currPage.getTitle();
String height = toolConfig.getPlacementConfig().getProperty(HEIGHT_PROP);
webContentData.setAttribute(NEW_WINDOW, new Boolean(currPage.isPopUp()).toString());
try {
String encoded = new String(codec.encode(contentUrl.getBytes("UTF-8")),"UTF-8");
webContentData.setAttribute(WEB_CONTENT_URL, encoded);
}
catch(Exception e) {
M_log.warn("Encode Web Content URL - " + e);
}
try {
String encoded = new String(codec.encode(toolTitle.getBytes("UTF-8")),"UTF-8");
webContentData.setAttribute(WEB_CONTENT_TITLE, encoded);
}
catch(Exception e) {
M_log.warn("Encode Web Content Tool Title - " + e);
}
if (height != null) {
webContentData.setAttribute(HEIGHT_PROP, height);
}
try {
String encoded = new String(codec.encode(pageTitle.getBytes("UTF-8")),"UTF-8");
webContentData.setAttribute(PAGE_TITLE, encoded);
}
catch(Exception e) {
M_log.warn("Encode Web Content Page Title - " + e);
}
if (height != null) {
webContentData.setAttribute(HEIGHT_PROP, height);
}
webContentEl.appendChild(webContentData);
}
}
}
results.append("archiving " + getLabel() + ": (" + count
+ ") web content items archived successfully.\n");
}
else {
results.append("archiving " + getLabel()
+ ": empty web content archived.\n");
}
((Element) stack.peek()).appendChild(webContentEl);
stack.push(webContentEl);
}
stack.pop();
}
catch (DOMException e)
{
M_log.error(e.getMessage(), e);
}
catch (IdUnusedException e)
{
M_log.error(e.getMessage(), e);
}
catch (Exception e)
{
M_log.error(e.getMessage(), e);
}
return results.toString();
}
public Entity getEntity(Reference ref)
{
// TODO Auto-generated method stub
return null;
}
public Collection getEntityAuthzGroups(Reference ref)
{
// TODO Auto-generated method stub
return null;
}
public String getEntityDescription(Reference ref)
{
// TODO Auto-generated method stub
return null;
}
public ResourceProperties getEntityResourceProperties(Reference ref)
{
// TODO Auto-generated method stub
return null;
}
public String getEntityUrl(Reference ref)
{
// TODO Auto-generated method stub
return null;
}
public HttpAccess getHttpAccess()
{
// TODO Auto-generated method stub
return null;
}
public String getLabel()
{
return "web";
}
public String merge(String siteId, Element root, String archivePath, String fromSiteId, Map attachmentNames, Map userIdTrans, Set userListAllowImport)
{
M_log.info("merge starts for Web Content...");
Base64 codec = new Base64();
if (siteId != null && siteId.trim().length() > 0)
{
try
{
Site site = SiteService.getSite(siteId);
NodeList allChildrenNodes = root.getChildNodes();
int length = allChildrenNodes.getLength();
for (int i = 0; i < length; i++)
{
Node siteNode = allChildrenNodes.item(i);
if (siteNode.getNodeType() == Node.ELEMENT_NODE)
{
Element siteElement = (Element) siteNode;
if (siteElement.getTagName().equals(WEB_CONTENT))
{
NodeList allContentNodes = siteElement.getChildNodes();
int lengthContent = allContentNodes.getLength();
for (int j = 0; j < lengthContent; j++)
{
Node child1 = allContentNodes.item(j);
if (child1.getNodeType() == Node.ELEMENT_NODE)
{
Element contentElement = (Element) child1;
if (contentElement.getTagName().equals(REDIRECT_TAB))
{
String toolTitle = contentElement.getAttribute(WEB_CONTENT_TITLE);
String trimBody = null;
if(toolTitle != null && toolTitle.length() >0)
{
trimBody = trimToNull(toolTitle);
if (trimBody != null && trimBody.length() >0)
{
byte[] decoded = codec.decode(trimBody.getBytes("UTF-8"));
toolTitle = new String(decoded, "UTF-8");
}
}
String pageTitle = contentElement.getAttribute(PAGE_TITLE);
trimBody = null;
if(pageTitle != null && pageTitle.length() >0)
{
trimBody = trimToNull(pageTitle);
if (trimBody != null && trimBody.length() >0)
{
byte[] decoded = codec.decode(trimBody.getBytes("UTF-8"));
pageTitle = new String(decoded, "UTF-8");
}
}
// if either tool or page title is missing, use the same for both
if ((toolTitle != null && toolTitle.length() > 0) && (pageTitle == null || pageTitle.length() == 0))
pageTitle = toolTitle;
if ((pageTitle != null && pageTitle.length() > 0) && (toolTitle == null || toolTitle.length() == 0))
toolTitle = pageTitle;
String contentUrl = contentElement.getAttribute(WEB_CONTENT_URL);
trimBody = null;
if(contentUrl != null && contentUrl.length() >0)
{
trimBody = trimToNull(contentUrl);
if (trimBody != null && trimBody.length() >0)
{
byte[] decoded = codec.decode(trimBody.getBytes("UTF-8"));
contentUrl = new String(decoded, "UTF-8");
}
}
String height = contentElement.getAttribute(HEIGHT_PROP);
String openInNewWindow = contentElement.getAttribute(NEW_WINDOW);
if(toolTitle != null && contentUrl != null && toolTitle.length() >0 && contentUrl.length() >0
&& pageTitle !=null && pageTitle.length() > 0)
{
Tool tr = ToolManager.getTool(TOOL_ID);
SitePage page = site.addPage();
page.setTitle(pageTitle);
ToolConfiguration tool = page.addTool();
tool.setTool(TOOL_ID, tr);
tool.setTitle(toolTitle);
tool.getPlacementConfig().setProperty(WEB_CONTENT_URL_PROP, contentUrl);
if (height != null) {
tool.getPlacementConfig().setProperty(HEIGHT_PROP, height);
}
if (openInNewWindow.equalsIgnoreCase("true"))
page.setPopup(true);
else
page.setPopup(false);
}
else
{
M_log.warn("Web content item not imported because page_title and title missing or url missing: " + "title: " + toolTitle + " page_title: " + pageTitle + " url: " + contentUrl);
}
}
}
}
}
}
}
SiteService.save(site);
ToolSession session = SessionManager.getCurrentToolSession();
// During site import, ToolSession may not yet be established
if (session != null && session.getAttribute(ATTR_TOP_REFRESH) == null)
{
session.setAttribute(ATTR_TOP_REFRESH, Boolean.TRUE);
}
}
catch(Exception e)
{
M_log.error("errors in merge for WebServiceImpl");
e.printStackTrace();
}
}
return null;
}
public boolean parseEntityReference(String reference, Reference ref)
{
// TODO Auto-generated method stub
return false;
}
public boolean willArchiveMerge()
{
// TODO Auto-generated method stub
return true;
}
public String[] myToolIds()
{
String[] toolIds = { TOOL_ID };
return toolIds;
}
public void transferCopyEntities(String fromContext, String toContext, List ids)
{
M_log.debug("web content transferCopyEntities");
try
{
// retrieve all of the web content tools to copy
Site fromSite = SiteService.getSite(fromContext);
Site toSite = SiteService.getSite(toContext);
List fromSitePages = fromSite.getPages();
if (fromSitePages != null && !fromSitePages.isEmpty()) {
Iterator pageIter = fromSitePages.iterator();
while (pageIter.hasNext()) {
SitePage currPage = (SitePage) pageIter.next();
List toolList = currPage.getTools();
Iterator toolIter = toolList.iterator();
while (toolIter.hasNext()) {
ToolConfiguration toolConfig = (ToolConfiguration)toolIter.next();
// we do not want to import "special" uses of sakai.iframe, such as worksite info
String special = toolConfig.getPlacementConfig().getProperty(SPECIAL_PROP);
if (toolConfig.getToolId().equals(TOOL_ID) && special == null) {
String contentUrl = toolConfig.getPlacementConfig().getProperty(WEB_CONTENT_URL_PROP);
String toolTitle = toolConfig.getTitle();
String pageTitle = currPage.getTitle();
String height = toolConfig.getPlacementConfig().getProperty(HEIGHT_PROP);
// in some cases the new site already has all of this. so make
// sure we don't make a duplicate
boolean skip = false;
String[] toolIds = {TOOL_ID};
Collection<ToolConfiguration> toolConfs = toSite.getTools(TOOL_ID);
if (toolConfs != null && !toolConfs.isEmpty()) {
for (ToolConfiguration config: toolConfs) {
if (config.getToolId().equals(TOOL_ID)) {
SitePage p = config.getContainingPage();
if (pageTitle != null &&
pageTitle.equals(p.getTitle()) &&
contentUrl != null &&
contentUrl.equals(config.getPlacementConfig().getProperty(WEB_CONTENT_URL_PROP))) {
skip = true;
break;
}
}
}
}
if(!skip && toolTitle != null && toolTitle.length() >0 && pageTitle !=null && pageTitle.length() > 0)
{
Tool tr = ToolManager.getTool(TOOL_ID);
SitePage page = toSite.addPage();
page.setTitle(pageTitle);
ToolConfiguration tool = page.addTool();
tool.setTool(TOOL_ID, tr);
tool.setTitle(toolTitle);
if (contentUrl != null) {
// Replace references to the site we're copying from.
contentUrl = contentUrl.replace(fromContext, toContext);
tool.getPlacementConfig().setProperty(WEB_CONTENT_URL_PROP, contentUrl);
}
if (height != null) {
tool.getPlacementConfig().setProperty(HEIGHT_PROP, height);
}
if (currPage.isPopUp())
page.setPopup(true);
else
page.setPopup(false);
}
}
}
}
}
SiteService.save(toSite);
ToolSession session = SessionManager.getCurrentToolSession();
if (session != null && session.getAttribute(ATTR_TOP_REFRESH) == null)
{
session.setAttribute(ATTR_TOP_REFRESH, Boolean.TRUE);
}
}
catch (Exception any)
{
M_log.warn("transferCopyEntities(): exception in handling webcontent data: ", any);
}
}
public String trimToNull(String value)
{
if (value == null) return null;
value = value.trim();
if (value.length() == 0) return null;
return value;
}
public Collection getEntityAuthzGroups(Reference ref, String userId)
{
// TODO Auto-generated method stub
return null;
}
public void transferCopyEntities(String fromContext, String toContext, List ids, boolean cleanup)
{
try
{
if(cleanup == true)
{
Site toSite = SiteService.getSite(toContext);
List toSitePages = toSite.getPages();
if (toSitePages != null && !toSitePages.isEmpty())
{
Vector removePageIds = new Vector();
Iterator pageIter = toSitePages.iterator();
while (pageIter.hasNext())
{
SitePage currPage = (SitePage) pageIter.next();
List toolList = currPage.getTools();
Iterator toolIter = toolList.iterator();
while (toolIter.hasNext())
{
ToolConfiguration toolConfig = (ToolConfiguration)toolIter.next();
// we do not want to import "special" uses of sakai.iframe, such as worksite info
String special = toolConfig.getPlacementConfig().getProperty(SPECIAL_PROP);
if (toolConfig.getToolId().equals(TOOL_ID) && special == null)
{
removePageIds.add(toolConfig.getPageId());
}
}
}
for (int i = 0; i < removePageIds.size(); i++)
{
String removeId = (String) removePageIds.get(i);
SitePage sitePage = toSite.getPage(removeId);
toSite.removePage(sitePage);
}
}
SiteService.save(toSite);
ToolSession session = SessionManager.getCurrentToolSession();
if (session != null && session.getAttribute(ATTR_TOP_REFRESH) == null)
{
session.setAttribute(ATTR_TOP_REFRESH, Boolean.TRUE);
}
}
transferCopyEntities(fromContext, toContext, ids);
}
catch (Exception e)
{
M_log.info("WebContent transferCopyEntities Error" + e);
}
}
}