001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/web/trunk/web-impl/impl/src/java/org/sakaiproject/web/impl/WebServiceImpl.java$
003: * $Id: WebServiceImpl.java 9227 2006-06-22 02:02:42Z cwen@iupui.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.web.impl;
021:
022: import java.util.Collection;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Map;
026: import java.util.Set;
027: import java.util.Stack;
028: import java.util.Vector;
029:
030: import org.apache.commons.codec.binary.Base64;
031: import org.apache.commons.logging.Log;
032: import org.apache.commons.logging.LogFactory;
033: import org.sakaiproject.entity.api.Entity;
034: import org.sakaiproject.entity.api.EntityTransferrer;
035: import org.sakaiproject.entity.api.HttpAccess;
036: import org.sakaiproject.entity.api.Reference;
037: import org.sakaiproject.entity.api.ResourceProperties;
038: import org.sakaiproject.entity.cover.EntityManager;
039: import org.sakaiproject.exception.IdUnusedException;
040: import org.sakaiproject.site.api.Site;
041: import org.sakaiproject.site.api.SitePage;
042: import org.sakaiproject.site.api.ToolConfiguration;
043: import org.sakaiproject.tool.api.Tool;
044: import org.sakaiproject.tool.api.ToolSession;
045: import org.sakaiproject.tool.cover.SessionManager;
046: import org.sakaiproject.tool.cover.ToolManager;
047: import org.sakaiproject.site.cover.SiteService;
048: import org.sakaiproject.web.api.WebService;
049: import org.w3c.dom.DOMException;
050: import org.w3c.dom.Document;
051: import org.w3c.dom.Element;
052: import org.w3c.dom.Node;
053: import org.w3c.dom.NodeList;
054:
055: public class WebServiceImpl implements WebService, EntityTransferrer {
056:
057: private static Log M_log = LogFactory.getLog(WebServiceImpl.class);
058:
059: private static final String TOOL_ID = "sakai.iframe";
060:
061: private static final String WEB_CONTENT = "web_content";
062: private static final String REDIRECT_TAB = "redirect_tab";
063: private static final String WEB_CONTENT_TITLE = "title";
064: private static final String WEB_CONTENT_URL = "url";
065: private static final String PAGE_TITLE = "page_title";
066: private static final String NEW_WINDOW = "open_in_new_window";
067: private static final String ARCHIVE_VERSION = "2.4"; // in case new features are added in future exports
068:
069: private static final String VERSION_ATTR = "version";
070: private static final String WEB_CONTENT_URL_PROP = "source";
071: private static final String HEIGHT_PROP = "height";
072: private static final String SPECIAL_PROP = "special";
073:
074: public static final String ATTR_TOP_REFRESH = "sakai.vppa.top.refresh";
075:
076: public void init() {
077: M_log.debug("init()");
078:
079: // register as an entity producer
080: EntityManager.registerEntityProducer(this , REFERENCE_ROOT);
081:
082: } // init
083:
084: public String archive(String siteId, Document doc, Stack stack,
085: String archivePath, List attachments) {
086: StringBuffer results = new StringBuffer();
087:
088: Base64 codec = new Base64();
089: try {
090: int count = 0;
091: results.append("archiving " + getLabel() + " context "
092: + Entity.SEPARATOR + siteId + Entity.SEPARATOR
093: + SiteService.MAIN_CONTAINER + ".\n");
094: // start with an element with our very own (service) name
095: Element element = doc.createElement(SERVICE_NAME);
096: element.setAttribute(VERSION_ATTR, ARCHIVE_VERSION);
097: ((Element) stack.peek()).appendChild(element);
098: stack.push(element);
099: if (siteId != null && siteId.trim().length() > 0) {
100: Element webContentEl = doc.createElement(WEB_CONTENT);
101:
102: Site site = SiteService.getSite(siteId);
103: List sitePages = site.getPages();
104:
105: if (sitePages != null && !sitePages.isEmpty()) {
106: Iterator pageIter = sitePages.iterator();
107: while (pageIter.hasNext()) {
108: SitePage currPage = (SitePage) pageIter.next();
109:
110: List toolList = currPage.getTools();
111: Iterator toolIter = toolList.iterator();
112: while (toolIter.hasNext()) {
113: ToolConfiguration toolConfig = (ToolConfiguration) toolIter
114: .next();
115:
116: // we do not want to archive "special" uses of sakai.iframe, such as worksite info
117: String special = toolConfig
118: .getPlacementConfig().getProperty(
119: SPECIAL_PROP);
120:
121: if (toolConfig.getToolId().equals(TOOL_ID)
122: && special == null) {
123: Element webContentData = doc
124: .createElement(REDIRECT_TAB);
125: count++;
126:
127: String contentUrl = toolConfig
128: .getPlacementConfig()
129: .getProperty(
130: WEB_CONTENT_URL_PROP);
131: String toolTitle = toolConfig
132: .getTitle();
133: String pageTitle = currPage.getTitle();
134: String height = toolConfig
135: .getPlacementConfig()
136: .getProperty(HEIGHT_PROP);
137:
138: webContentData.setAttribute(NEW_WINDOW,
139: new Boolean(currPage.isPopUp())
140: .toString());
141:
142: try {
143: String encoded = new String(
144: codec.encode(contentUrl
145: .getBytes("UTF-8")),
146: "UTF-8");
147: webContentData.setAttribute(
148: WEB_CONTENT_URL, encoded);
149: } catch (Exception e) {
150: M_log
151: .warn("Encode Web Content URL - "
152: + e);
153: }
154:
155: try {
156: String encoded = new String(
157: codec.encode(toolTitle
158: .getBytes("UTF-8")),
159: "UTF-8");
160: webContentData.setAttribute(
161: WEB_CONTENT_TITLE, encoded);
162: } catch (Exception e) {
163: M_log
164: .warn("Encode Web Content Tool Title - "
165: + e);
166: }
167:
168: if (height != null) {
169: webContentData.setAttribute(
170: HEIGHT_PROP, height);
171: }
172:
173: try {
174: String encoded = new String(
175: codec.encode(pageTitle
176: .getBytes("UTF-8")),
177: "UTF-8");
178: webContentData.setAttribute(
179: PAGE_TITLE, encoded);
180: } catch (Exception e) {
181: M_log
182: .warn("Encode Web Content Page Title - "
183: + e);
184: }
185:
186: if (height != null) {
187: webContentData.setAttribute(
188: HEIGHT_PROP, height);
189: }
190:
191: webContentEl
192: .appendChild(webContentData);
193: }
194: }
195: }
196: results
197: .append("archiving "
198: + getLabel()
199: + ": ("
200: + count
201: + ") web content items archived successfully.\n");
202: }
203:
204: else {
205: results.append("archiving " + getLabel()
206: + ": empty web content archived.\n");
207: }
208:
209: ((Element) stack.peek()).appendChild(webContentEl);
210: stack.push(webContentEl);
211: }
212: stack.pop();
213:
214: } catch (DOMException e) {
215: M_log.error(e.getMessage(), e);
216: } catch (IdUnusedException e) {
217: M_log.error(e.getMessage(), e);
218: } catch (Exception e) {
219: M_log.error(e.getMessage(), e);
220: }
221: return results.toString();
222: }
223:
224: public Entity getEntity(Reference ref) {
225: // TODO Auto-generated method stub
226: return null;
227: }
228:
229: public Collection getEntityAuthzGroups(Reference ref) {
230: // TODO Auto-generated method stub
231: return null;
232: }
233:
234: public String getEntityDescription(Reference ref) {
235: // TODO Auto-generated method stub
236: return null;
237: }
238:
239: public ResourceProperties getEntityResourceProperties(Reference ref) {
240: // TODO Auto-generated method stub
241: return null;
242: }
243:
244: public String getEntityUrl(Reference ref) {
245: // TODO Auto-generated method stub
246: return null;
247: }
248:
249: public HttpAccess getHttpAccess() {
250: // TODO Auto-generated method stub
251: return null;
252: }
253:
254: public String getLabel() {
255: return "web";
256: }
257:
258: public String merge(String siteId, Element root,
259: String archivePath, String fromSiteId, Map attachmentNames,
260: Map userIdTrans, Set userListAllowImport) {
261: M_log.info("merge starts for Web Content...");
262: Base64 codec = new Base64();
263: if (siteId != null && siteId.trim().length() > 0) {
264: try {
265: Site site = SiteService.getSite(siteId);
266: NodeList allChildrenNodes = root.getChildNodes();
267: int length = allChildrenNodes.getLength();
268: for (int i = 0; i < length; i++) {
269: Node siteNode = allChildrenNodes.item(i);
270: if (siteNode.getNodeType() == Node.ELEMENT_NODE) {
271: Element siteElement = (Element) siteNode;
272: if (siteElement.getTagName()
273: .equals(WEB_CONTENT)) {
274: NodeList allContentNodes = siteElement
275: .getChildNodes();
276: int lengthContent = allContentNodes
277: .getLength();
278: for (int j = 0; j < lengthContent; j++) {
279: Node child1 = allContentNodes.item(j);
280: if (child1.getNodeType() == Node.ELEMENT_NODE) {
281: Element contentElement = (Element) child1;
282: if (contentElement.getTagName()
283: .equals(REDIRECT_TAB)) {
284: String toolTitle = contentElement
285: .getAttribute(WEB_CONTENT_TITLE);
286: String trimBody = null;
287: if (toolTitle != null
288: && toolTitle.length() > 0) {
289: trimBody = trimToNull(toolTitle);
290: if (trimBody != null
291: && trimBody
292: .length() > 0) {
293: byte[] decoded = codec
294: .decode(trimBody
295: .getBytes("UTF-8"));
296: toolTitle = new String(
297: decoded,
298: "UTF-8");
299: }
300: }
301:
302: String pageTitle = contentElement
303: .getAttribute(PAGE_TITLE);
304: trimBody = null;
305: if (pageTitle != null
306: && pageTitle.length() > 0) {
307: trimBody = trimToNull(pageTitle);
308: if (trimBody != null
309: && trimBody
310: .length() > 0) {
311: byte[] decoded = codec
312: .decode(trimBody
313: .getBytes("UTF-8"));
314: pageTitle = new String(
315: decoded,
316: "UTF-8");
317: }
318: }
319:
320: // if either tool or page title is missing, use the same for both
321: if ((toolTitle != null && toolTitle
322: .length() > 0)
323: && (pageTitle == null || pageTitle
324: .length() == 0))
325: pageTitle = toolTitle;
326: if ((pageTitle != null && pageTitle
327: .length() > 0)
328: && (toolTitle == null || toolTitle
329: .length() == 0))
330: toolTitle = pageTitle;
331:
332: String contentUrl = contentElement
333: .getAttribute(WEB_CONTENT_URL);
334: trimBody = null;
335: if (contentUrl != null
336: && contentUrl.length() > 0) {
337: trimBody = trimToNull(contentUrl);
338: if (trimBody != null
339: && trimBody
340: .length() > 0) {
341: byte[] decoded = codec
342: .decode(trimBody
343: .getBytes("UTF-8"));
344: contentUrl = new String(
345: decoded,
346: "UTF-8");
347: }
348: }
349:
350: String height = contentElement
351: .getAttribute(HEIGHT_PROP);
352: String openInNewWindow = contentElement
353: .getAttribute(NEW_WINDOW);
354:
355: if (toolTitle != null
356: && contentUrl != null
357: && toolTitle.length() > 0
358: && contentUrl.length() > 0
359: && pageTitle != null
360: && pageTitle.length() > 0) {
361: Tool tr = ToolManager
362: .getTool(TOOL_ID);
363: SitePage page = site
364: .addPage();
365: page.setTitle(pageTitle);
366: ToolConfiguration tool = page
367: .addTool();
368: tool.setTool(TOOL_ID, tr);
369: tool.setTitle(toolTitle);
370: tool
371: .getPlacementConfig()
372: .setProperty(
373: WEB_CONTENT_URL_PROP,
374: contentUrl);
375:
376: if (height != null) {
377: tool
378: .getPlacementConfig()
379: .setProperty(
380: HEIGHT_PROP,
381: height);
382: }
383:
384: if (openInNewWindow
385: .equalsIgnoreCase("true"))
386: page.setPopup(true);
387: else
388: page.setPopup(false);
389: } else {
390: M_log
391: .warn("Web content item not imported because page_title and title missing or url missing: "
392: + "title: "
393: + toolTitle
394: + " page_title: "
395: + pageTitle
396: + " url: "
397: + contentUrl);
398: }
399: }
400: }
401: }
402: }
403: }
404: }
405: SiteService.save(site);
406: ToolSession session = SessionManager
407: .getCurrentToolSession();
408:
409: if (session.getAttribute(ATTR_TOP_REFRESH) == null) {
410: session
411: .setAttribute(ATTR_TOP_REFRESH,
412: Boolean.TRUE);
413: }
414: } catch (Exception e) {
415: M_log.error("errors in merge for WebServiceImpl");
416: e.printStackTrace();
417: }
418: }
419:
420: return null;
421: }
422:
423: public boolean parseEntityReference(String reference, Reference ref) {
424: // TODO Auto-generated method stub
425: return false;
426: }
427:
428: public boolean willArchiveMerge() {
429: // TODO Auto-generated method stub
430: return true;
431: }
432:
433: public String[] myToolIds() {
434: String[] toolIds = { TOOL_ID };
435: return toolIds;
436: }
437:
438: public void transferCopyEntities(String fromContext,
439: String toContext, List ids) {
440: M_log.debug("web content transferCopyEntities");
441: try {
442: // retrieve all of the web content tools to copy
443: Site fromSite = SiteService.getSite(fromContext);
444: Site toSite = SiteService.getSite(toContext);
445:
446: List fromSitePages = fromSite.getPages();
447:
448: if (fromSitePages != null && !fromSitePages.isEmpty()) {
449: Iterator pageIter = fromSitePages.iterator();
450: while (pageIter.hasNext()) {
451: SitePage currPage = (SitePage) pageIter.next();
452:
453: List toolList = currPage.getTools();
454: Iterator toolIter = toolList.iterator();
455: while (toolIter.hasNext()) {
456: ToolConfiguration toolConfig = (ToolConfiguration) toolIter
457: .next();
458:
459: // we do not want to import "special" uses of sakai.iframe, such as worksite info
460: String special = toolConfig
461: .getPlacementConfig().getProperty(
462: SPECIAL_PROP);
463:
464: if (toolConfig.getToolId().equals(TOOL_ID)
465: && special == null) {
466: String contentUrl = toolConfig
467: .getPlacementConfig().getProperty(
468: WEB_CONTENT_URL_PROP);
469: String toolTitle = toolConfig.getTitle();
470: String pageTitle = currPage.getTitle();
471: String height = toolConfig
472: .getPlacementConfig().getProperty(
473: HEIGHT_PROP);
474:
475: if (toolTitle != null
476: && toolTitle.length() > 0
477: && pageTitle != null
478: && pageTitle.length() > 0) {
479: Tool tr = ToolManager.getTool(TOOL_ID);
480: SitePage page = toSite.addPage();
481: page.setTitle(pageTitle);
482: ToolConfiguration tool = page.addTool();
483: tool.setTool(TOOL_ID, tr);
484: tool.setTitle(toolTitle);
485: if (contentUrl != null) {
486: tool
487: .getPlacementConfig()
488: .setProperty(
489: WEB_CONTENT_URL_PROP,
490: contentUrl);
491: }
492:
493: if (height != null) {
494: tool.getPlacementConfig()
495: .setProperty(HEIGHT_PROP,
496: height);
497: }
498:
499: if (currPage.isPopUp())
500: page.setPopup(true);
501: else
502: page.setPopup(false);
503: }
504: }
505: }
506: }
507: }
508: SiteService.save(toSite);
509: ToolSession session = SessionManager
510: .getCurrentToolSession();
511:
512: if (session.getAttribute(ATTR_TOP_REFRESH) == null) {
513: session.setAttribute(ATTR_TOP_REFRESH, Boolean.TRUE);
514: }
515: }
516:
517: catch (Exception any) {
518: M_log
519: .warn(
520: "transferCopyEntities(): exception in handling webcontent data: ",
521: any);
522: }
523:
524: }
525:
526: public String trimToNull(String value) {
527: if (value == null)
528: return null;
529: value = value.trim();
530: if (value.length() == 0)
531: return null;
532: return value;
533: }
534:
535: public Collection getEntityAuthzGroups(Reference ref, String userId) {
536: // TODO Auto-generated method stub
537: return null;
538: }
539:
540: }
|