001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/portal/tags/sakai_2-4-1/portal-render-impl/impl/src/java/org/sakaiproject/portal/render/fragment/FragmentToolRenderService.java $
003: * $Id: FragmentToolRenderService.java 29143 2007-04-19 01:10:38Z ajpoland@iupui.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 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.portal.render.fragment;
021:
022: import java.io.IOException;
023: import java.util.Properties;
024:
025: import javax.servlet.ServletContext;
026: import javax.servlet.http.HttpServletRequest;
027: import javax.servlet.http.HttpServletResponse;
028:
029: import org.apache.commons.logging.Log;
030: import org.apache.commons.logging.LogFactory;
031: import org.sakaiproject.component.cover.ServerConfigurationService;
032: import org.sakaiproject.exception.IdUnusedException;
033: import org.sakaiproject.exception.PermissionException;
034: import org.sakaiproject.portal.api.PortalService;
035: import org.sakaiproject.portal.api.StoredState;
036: import org.sakaiproject.portal.render.api.RenderResult;
037: import org.sakaiproject.portal.render.api.ToolRenderException;
038: import org.sakaiproject.portal.render.api.ToolRenderService;
039: import org.sakaiproject.portal.util.ToolURLManagerImpl;
040: import org.sakaiproject.site.api.Site;
041: import org.sakaiproject.site.api.ToolConfiguration;
042: import org.sakaiproject.site.cover.SiteService;
043: import org.sakaiproject.tool.api.ActiveTool;
044: import org.sakaiproject.tool.api.Placement;
045: import org.sakaiproject.tool.api.Session;
046: import org.sakaiproject.tool.api.Tool;
047: import org.sakaiproject.tool.api.ToolException;
048: import org.sakaiproject.tool.api.ToolSession;
049: import org.sakaiproject.tool.api.ToolURL;
050: import org.sakaiproject.tool.cover.ActiveToolManager;
051: import org.sakaiproject.tool.cover.SessionManager;
052: import org.sakaiproject.util.Web;
053:
054: /**
055: * Attempts to render a tool as a fragment rather than an Iframe.
056: *
057: * @author ieb
058: * @since Sakai 2.4
059: * @version $Rev: 29143 $
060: */
061: public class FragmentToolRenderService implements ToolRenderService {
062:
063: private static final String TOOL_FRAGMENT_PRODUCER_ID = "fragment-producer";
064:
065: private static final Log log = LogFactory
066: .getLog(FragmentToolRenderService.class);
067:
068: private PortalService portal;
069:
070: public FragmentToolRenderService() {
071: }
072:
073: /**
074: * This is called during render to accept the request into this tool. If the
075: * placement is handled by the FragmentToolRenderService, this should return
076: * true, then the render will be invoked.
077: */
078: public boolean accept(ToolConfiguration configuration,
079: HttpServletRequest request, HttpServletResponse response,
080: ServletContext context) {
081: return isFragmentTool(configuration);
082: }
083:
084: private boolean isFragmentTool(ToolConfiguration configuration) {
085: Properties placementProperties = configuration.getConfig();
086: String fragmentCapable = placementProperties
087: .getProperty(TOOL_FRAGMENT_PRODUCER_ID);
088:
089: if (fragmentCapable == null || fragmentCapable.length() == 0) {
090: return false;
091: }
092: return true;
093: }
094:
095: public boolean preprocess(HttpServletRequest request,
096: HttpServletResponse response, ServletContext context)
097: throws IOException {
098: // for fragments there is no preprocessing, as this is all performed in
099: // the render cycle
100: return true;
101: }
102:
103: public RenderResult render(
104: final ToolConfiguration toolConfiguration,
105: final HttpServletRequest request,
106: final HttpServletResponse response, ServletContext context)
107: throws IOException, ToolRenderException {
108: if (isFragmentTool(toolConfiguration)) {
109: return new RenderResult() {
110:
111: public String getContent() throws ToolRenderException {
112: Session session = SessionManager
113: .getCurrentSession();
114: // recognize what to do from the path
115: String option = request.getPathInfo();
116:
117: // if missing, set it to home or gateway
118: if ((option == null) || ("/".equals(option))) {
119: if (session.getUserId() == null) {
120: option = "/site/"
121: + ServerConfigurationService
122: .getGatewaySiteId();
123: } else {
124: option = "/site/"
125: + SiteService.getUserSiteId(session
126: .getUserId());
127: }
128: }
129:
130: // get the parts (the first will be "")
131: String[] parts = option.split("/");
132:
133: try {
134: doTool(toolConfiguration, request, response,
135: session, toolConfiguration.getId(),
136: request.getContextPath()
137: + request.getServletPath()
138: + Web.makePath(parts, 1, 3),
139: Web.makePath(parts, 3, parts.length));
140: } catch (Exception e) {
141: throw new ToolRenderException(
142: "Failed to perform render ", e);
143: }
144:
145: // include will render to the output stream
146: return "";
147: }
148:
149: public String getTitle() throws ToolRenderException {
150: return Web.escapeHtml(toolConfiguration.getTitle());
151: }
152:
153: public String getJSR168EditUrl() {
154: return null;
155: }
156:
157: public String getJSR168HelpUrl() {
158: return null;
159: }
160: };
161: // do a named dispatch to the active tool with a fragment set
162:
163: }
164: return null;
165: }
166:
167: protected void doTool(ToolConfiguration toolConfiguration,
168: HttpServletRequest req, HttpServletResponse res,
169: Session session, String placementId,
170: String toolContextPath, String toolPathInfo)
171: throws ToolException, IOException {
172:
173: // Reset the tool state if requested
174: if (portal.isResetRequested(req)) {
175: Session s = SessionManager.getCurrentSession();
176: ToolSession ts = s.getToolSession(placementId);
177: ts.clearAttributes();
178: }
179:
180: // find the tool registered for this
181: ActiveTool tool = ActiveToolManager
182: .getActiveTool(toolConfiguration.getToolId());
183: if (tool == null) {
184: throw new ToolRenderException(
185: "Failed to render fragment, no Active Tool found for "
186: + toolConfiguration.getToolId());
187: }
188:
189: // permission check - visit the site (unless the tool is configured to
190: // bypass)
191: if (tool.getAccessSecurity() == Tool.AccessSecurity.PORTAL) {
192: Site site = null;
193: try {
194: site = SiteService.getSiteVisit(toolConfiguration
195: .getSiteId());
196: } catch (IdUnusedException e) {
197: throw new ToolRenderException(
198: "No site permissions found for site "
199: + toolConfiguration.getSiteId());
200: } catch (PermissionException e) {
201: throw new ToolRenderException(
202: "Permission Deined for placement "
203: + toolConfiguration.getId() + " in "
204: + toolConfiguration.getSiteId());
205: }
206: }
207:
208: forwardTool(tool, req, res, toolConfiguration,
209: toolConfiguration.getSkin(), toolContextPath,
210: toolPathInfo);
211: }
212:
213: /**
214: * Taken from Charon, should be in a service
215: *
216: * @param tool
217: * @param req
218: * @param res
219: * @param p
220: * @param skin
221: * @param toolContextPath
222: * @param toolPathInfo
223: * @throws ToolException
224: */
225: protected void forwardTool(ActiveTool tool, HttpServletRequest req,
226: HttpServletResponse res, Placement p, String skin,
227: String toolContextPath, String toolPathInfo)
228: throws ToolException {
229:
230: // if there is a stored request state, and path, extract that from the
231: // session and
232: // reinstance it
233:
234: // let the tool do the the work (forward)
235: if (portal.isEnableDirect()) {
236: StoredState ss = portal.getStoredState();
237: if (ss == null
238: || !toolContextPath.equals(ss.getToolContextPath())) {
239: req.setAttribute(ToolURL.MANAGER,
240: new ToolURLManagerImpl(res));
241: tool
242: .include(req, res, p, toolContextPath,
243: toolPathInfo);
244: } else {
245: log.debug("Restoring Fragment StoredState [" + ss
246: + "]");
247:
248: HttpServletRequest sreq = ss.getRequest(req);
249: Placement splacement = ss.getPlacement();
250: String stoolContext = ss.getToolContextPath();
251: String stoolPathInfo = ss.getToolPathInfo();
252: ActiveTool stool = ActiveToolManager.getActiveTool(p
253: .getToolId());
254: String sskin = ss.getSkin();
255: req.setAttribute(ToolURL.MANAGER,
256: new ToolURLManagerImpl(res));
257: stool.include(sreq, res, splacement, stoolContext,
258: stoolPathInfo);
259: // this is correct as we have already checked the context path
260: // of the desitination
261: portal.setStoredState(null);
262: }
263: } else {
264: req.setAttribute(ToolURL.MANAGER, new ToolURLManagerImpl(
265: res));
266: tool.include(req, res, p, toolContextPath, toolPathInfo);
267: }
268:
269: }
270:
271: public void setPortalService(PortalService portal) {
272: this .portal = portal;
273: }
274:
275: public void reset(ToolConfiguration configuration) {
276: }
277: }
|