Index: .classpath =================================================================== --- .classpath (revision 43807) +++ .classpath (working copy) @@ -1,5 +1,6 @@ + Index: pom.xml =================================================================== --- pom.xml (revision 43807) +++ pom.xml (working copy) @@ -48,5 +48,6 @@ rwiki-util/jrcs rwiki-util/radeox rwiki-util/util + rwiki-access-tool Index: rwiki-access-tool/.classpath =================================================================== --- rwiki-access-tool/.classpath (revision 0) +++ rwiki-access-tool/.classpath (revision 0) @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + Index: rwiki-access-tool/.project =================================================================== --- rwiki-access-tool/.project (revision 0) +++ rwiki-access-tool/.project (revision 0) @@ -0,0 +1,17 @@ + + + rwiki-access-tool + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + Index: rwiki-access-tool/project.xml =================================================================== --- rwiki-access-tool/project.xml (revision 0) +++ rwiki-access-tool/project.xml (revision 0) @@ -0,0 +1,167 @@ + + + + 3 + ../../master/project.xml + wiki + sakaiproject + wiki + ${sakai.version} + + + + war + + + + + + sakaiproject + sakai-velocity-tool-api + ${sakai.version} + + + + sakaiproject + sakai-component-api + ${sakai.version} + + + + sakaiproject + sakai-content-api + ${sakai.version} + + + + sakaiproject + sakai-user-api + ${sakai.version} + + + + sakaiproject + sakai-event-api + ${sakai.version} + + + + commons-fileupload + commons-fileupload + 1.1.1 + + + + sakaiproject + sakai-authz-api + ${sakai.version} + + + + sakaiproject + sakai-entity-api + ${sakai.version} + + + + sakaiproject + sakai-util-api + ${sakai.version} + + + + sakaiproject + sakai-tool-api + ${sakai.version} + + + + commons-logging + commons-logging + 1.0.4 + + + + servletapi + servletapi + 2.4 + + + + sakaiproject + sakai-velocity-tool + ${sakai.version} + + true + + + + + sakaiproject + sakai-util + ${sakai.version} + + true + + + + + sakaiproject + sakai-entity-util + ${sakai.version} + + true + + + + + sakaiproject + sakai-user-util + ${sakai.version} + + true + + + + + + velocity + velocity + 1.3.1 + + true + + + + + logkit + logkit + 1.2 + + true + + + + + oro + oro + 2.0.8 + + true + + + + + + + + + src/java + + + + + + + + Index: rwiki-access-tool/pom.xml =================================================================== --- rwiki-access-tool/pom.xml (revision 0) +++ rwiki-access-tool/pom.xml (revision 0) @@ -0,0 +1,81 @@ + + + 4.0.0 + + master + org.sakaiproject + M2 + ../../master/pom.xml + + wiki + org.sakaiproject + wiki + + University of Michigan + http://sakaiproject.org/ + + 2003 + war + + + + org.sakaiproject + sakai-access-impl + ${sakai.version} + + + + org.sakaiproject + sakai-velocity-tool + ${sakai.version} + + + + org.sakaiproject + sakai-util + ${sakai.version} + + + + org.sakaiproject + sakai-entity-util + ${sakai.version} + + + + org.sakaiproject + sakai-user-util + ${sakai.version} + + + + + velocity + velocity + 1.3.1 + + + + logkit + logkit + 1.2 + + + + oro + oro + 2.0.8 + + + + + + + + + + + + + + Index: rwiki-access-tool/.classpath =================================================================== --- rwiki-access-tool/.classpath (revision 0) +++ rwiki-access-tool/.classpath (revision 0) @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + Index: rwiki-access-tool/.project =================================================================== --- rwiki-access-tool/.project (revision 0) +++ rwiki-access-tool/.project (revision 0) @@ -0,0 +1,17 @@ + + + rwiki-access-tool + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + Index: rwiki-access-tool/pom.xml =================================================================== --- rwiki-access-tool/pom.xml (revision 0) +++ rwiki-access-tool/pom.xml (revision 0) @@ -0,0 +1,81 @@ + + + 4.0.0 + + master + org.sakaiproject + M2 + ../../master/pom.xml + + wiki + org.sakaiproject + wiki + + University of Michigan + http://sakaiproject.org/ + + 2003 + war + + + + org.sakaiproject + sakai-access-impl + ${sakai.version} + + + + org.sakaiproject + sakai-velocity-tool + ${sakai.version} + + + + org.sakaiproject + sakai-util + ${sakai.version} + + + + org.sakaiproject + sakai-entity-util + ${sakai.version} + + + + org.sakaiproject + sakai-user-util + ${sakai.version} + + + + + velocity + velocity + 1.3.1 + + + + logkit + logkit + 1.2 + + + + oro + oro + 2.0.8 + + + + + + + + + + + + + + Index: rwiki-access-tool/project.xml =================================================================== --- rwiki-access-tool/project.xml (revision 0) +++ rwiki-access-tool/project.xml (revision 0) @@ -0,0 +1,167 @@ + + + + 3 + ../../master/project.xml + wiki + sakaiproject + wiki + ${sakai.version} + + + + war + + + + + + sakaiproject + sakai-velocity-tool-api + ${sakai.version} + + + + sakaiproject + sakai-component-api + ${sakai.version} + + + + sakaiproject + sakai-content-api + ${sakai.version} + + + + sakaiproject + sakai-user-api + ${sakai.version} + + + + sakaiproject + sakai-event-api + ${sakai.version} + + + + commons-fileupload + commons-fileupload + 1.1.1 + + + + sakaiproject + sakai-authz-api + ${sakai.version} + + + + sakaiproject + sakai-entity-api + ${sakai.version} + + + + sakaiproject + sakai-util-api + ${sakai.version} + + + + sakaiproject + sakai-tool-api + ${sakai.version} + + + + commons-logging + commons-logging + 1.0.4 + + + + servletapi + servletapi + 2.4 + + + + sakaiproject + sakai-velocity-tool + ${sakai.version} + + true + + + + + sakaiproject + sakai-util + ${sakai.version} + + true + + + + + sakaiproject + sakai-entity-util + ${sakai.version} + + true + + + + + sakaiproject + sakai-user-util + ${sakai.version} + + true + + + + + + velocity + velocity + 1.3.1 + + true + + + + + logkit + logkit + 1.2 + + true + + + + + oro + oro + 2.0.8 + + true + + + + + + + + + src/java + + + + + + + + Index: rwiki-access-tool/src/java/uk/ac/cam/caret/sakai/rwiki/access/WikiAccessServlet.java =================================================================== --- rwiki-access-tool/src/java/uk/ac/cam/caret/sakai/rwiki/access/WikiAccessServlet.java (revision 0) +++ rwiki-access-tool/src/java/uk/ac/cam/caret/sakai/rwiki/access/WikiAccessServlet.java (revision 0) @@ -0,0 +1,428 @@ +/********************************************************************************** + * $URL$ + * $Id$ + *********************************************************************************** + * + * Copyright (c) 2006 The Sakai Foundation. + * + * Licensed under the Educational Community License, Version 1.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/ecl1.php + * + * 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 uk.ac.cam.caret.sakai.rwiki.access; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Enumeration; +import java.util.Properties; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.sakaiproject.cheftool.VmServlet; +import org.sakaiproject.entity.api.EntityAccessOverloadException; +import org.sakaiproject.entity.api.EntityNotDefinedException; +import org.sakaiproject.entity.api.EntityPermissionException; +import org.sakaiproject.entity.api.EntityProducer; +import org.sakaiproject.entity.api.HttpAccess; +import org.sakaiproject.entity.api.Reference; +import org.sakaiproject.entity.cover.EntityManager; +import org.sakaiproject.tool.api.ActiveTool; +import org.sakaiproject.tool.api.Session; +import org.sakaiproject.tool.api.Tool; +import org.sakaiproject.tool.api.ToolException; +import org.sakaiproject.tool.cover.ActiveToolManager; +import org.sakaiproject.tool.cover.SessionManager; +import org.sakaiproject.util.BasicAuth; +import org.sakaiproject.util.ParameterParser; +import org.sakaiproject.util.Validator; +import org.sakaiproject.util.Web; + +/** + *

+ * Wiki extends access: all references are assumed to be under "/wiki/site" + *

+ * + * @author Sakai Software Development Team + */ +public class WikiAccessServlet extends VmServlet +{ + /** Our log (commons). */ + private static Log M_log = LogFactory.getLog(WikiAccessServlet.class); + + /** set to true when init'ed. */ + protected boolean m_ready = false; + + protected BasicAuth basicAuth = null; + + /** delimiter for form multiple values */ + protected static final String FORM_VALUE_DELIMETER = "^"; + + /** init thread - so we don't wait in the actual init() call */ + public class WikiServletInit extends Thread + { + /** + * construct and start the init activity + */ + public WikiServletInit() + { + m_ready = false; + start(); + } + + /** + * run the init + */ + public void run() + { + m_ready = true; + } + } + + /** + * initialize the AccessServlet servlet + * + * @param config + * the servlet config parameter + * @exception ServletException + * in case of difficulties + */ + public void init(ServletConfig config) throws ServletException + { + super.init(config); + startInit(); + basicAuth = new BasicAuth(); + basicAuth.init(); + + } + + /** + * Start the initialization process + */ + public void startInit() + { + new WikiServletInit(); + } + + /** + * Set active session according to sessionId parameter + */ + private void setSession( HttpServletRequest req ) + { + String sessionId = req.getParameter("session"); + if ( sessionId != null) + { + Session session = SessionManager.getSession(sessionId); + + if (session != null) + { + session.setActive(); + SessionManager.setCurrentSession(session); + } + } + } + + /** + * respond to an HTTP GET request + * + * @param req + * HttpServletRequest object with the client request + * @param res + * HttpServletResponse object back to the client + * @exception ServletException + * in case of difficulties + * @exception IOException + * in case of difficulties + */ + public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException + { + setSession(req); + dispatch(req, res); + } + + + /** + * handle get and post communication from the user + * + * @param req + * HttpServletRequest object with the client request + * @param res + * HttpServletResponse object back to the client + */ + public void dispatch(HttpServletRequest req, HttpServletResponse res) throws ServletException + { + ParameterParser params = (ParameterParser) req.getAttribute(ATTR_PARAMS); + + // get the path info + String path = params.getPath(); + if (path == null) path = ""; + + if (!m_ready) + { + sendError(res, HttpServletResponse.SC_SERVICE_UNAVAILABLE); + return; + } + + // pre-process the path + String origPath = path; + path = preProcessPath(path, req); + + // what is being requested? + Reference ref = EntityManager.newReference(path); + + // get the incoming information + WikiServletInfo info = newInfo(req); + + // let the entity producer handle it + try + { + // make sure we have a valid reference with an entity producer we can talk to + EntityProducer service = ref.getEntityProducer(); + if (service == null) throw new EntityNotDefinedException(ref.getReference()); + + // get the producer's HttpAccess helper, it might not support one + HttpAccess access = service.getHttpAccess(); + if (access == null) throw new EntityNotDefinedException(ref.getReference()); + + // let the helper do the work + access.handleAccess(req, res, ref, null); + } + catch (EntityNotDefinedException e) + { + // the request was not valid in some way + sendError(res, HttpServletResponse.SC_NOT_FOUND); + return; + } + catch (EntityPermissionException e) + { + // the end user does not have permission - offer a login if there is no user id yet established + // if not permitted, and the user is the anon user, let them login + if (SessionManager.getCurrentSessionUserId() == null) + { + try { + doLogin(req, res, origPath); + } catch ( IOException ioex ) {} + return; + } + + // otherwise reject the request + sendError(res, HttpServletResponse.SC_FORBIDDEN); + } + catch (EntityAccessOverloadException e) + { + M_log.info("dispatch(): ref: " + ref.getReference() + e); + sendError(res, HttpServletResponse.SC_SERVICE_UNAVAILABLE); + } + catch (Throwable e) + { + M_log.warn("dispatch(): exception: ", e); + sendError(res, HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + + finally + { + // log + if (M_log.isDebugEnabled()) + M_log.debug("from:" + req.getRemoteAddr() + " path:" + params.getPath() + " options: " + info.optionsString() + + " time: " + info.getElapsedTime()); + } + } + + + + /** + * respond to an HTTP POST request; only to handle the login process + * + * @param req + * HttpServletRequest object with the client request + * @param res + * HttpServletResponse object back to the client + * @exception ServletException + * in case of difficulties + * @exception IOException + * in case of difficulties + */ + public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException + { + // catch the login helper posts + String option = req.getPathInfo(); + String[] parts = option.split("/"); + if ((parts.length == 2) && ((parts[1].equals("login")))) + { + doLogin(req, res, null); + } + else + { + sendError(res, HttpServletResponse.SC_NOT_FOUND); + } + } + + /** + * Make any changes needed to the path before final "ref" processing. + * + * @param path + * The path from the request. + * @param req + * The request object. + * @return The path to use to make the Reference for further processing. + */ + protected String preProcessPath(String path, HttpServletRequest req) + { + // everything we work with is down the "content" part of the Sakai access URL space + + // if path is just "/", we don't really know if the request was to .../SERVLET or .../SERVLET/ - we want to preserve the trailing slash + // the request URI will tell us + if ("/".equals(path) && !(req.getRequestURI().endsWith("/"))) return "/wiki/site"; + + return "/wiki/site" + path; + } + + /** + * Make a redirect to the login url. + * + * @param req + * HttpServletRequest object with the client request. + * @param res + * HttpServletResponse object back to the client. + * @param path + * The current request path, set ONLY if we want this to be where to redirect the user after successfull login + * @throws IOException + */ + protected void doLogin(HttpServletRequest req, HttpServletResponse res, String path) throws ToolException, IOException + { + // if basic auth is valid do that + if ( basicAuth.doAuth(req,res) ) { + //System.err.println("BASIC Auth Request Sent to the Browser "); + return; + } + + + // get the Sakai session + Session session = SessionManager.getCurrentSession(); + + // set the return path for after login if needed (Note: in session, not tool session, special for Login helper) + if (path != null) + { + // where to go after + session.setAttribute(Tool.HELPER_DONE_URL, Web.returnUrl(req, Validator.escapeUrl(path))); + } + + // check that we have a return path set; might have been done earlier + if (session.getAttribute(Tool.HELPER_DONE_URL) == null) + { + M_log.warn("doLogin - proceeding with null HELPER_DONE_URL"); + } + + // map the request to the helper, leaving the path after ".../options" for the helper + ActiveTool tool = ActiveToolManager.getActiveTool("sakai.login"); + String context = req.getContextPath() + req.getServletPath() + "/login"; + tool.help(req, res, context, "/login"); + } + + protected void sendError(HttpServletResponse res, int code) + { + try + { + res.sendError(code); + } + catch (Throwable t) + { + M_log.warn("sendError: " + t); + } + } + + /** create the info */ + protected WikiServletInfo newInfo(HttpServletRequest req) + { + return new WikiServletInfo(req); + } + + public class WikiServletInfo + { + // elapsed time start + protected long m_startTime = System.currentTimeMillis(); + + public long getStartTime() + { + return m_startTime; + } + + public long getElapsedTime() + { + return System.currentTimeMillis() - m_startTime; + } + + // all properties from the request + protected Properties m_options = null; + + /** construct from the req */ + public WikiServletInfo(HttpServletRequest req) + { + m_options = new Properties(); + String type = req.getContentType(); + + Enumeration e = req.getParameterNames(); + while (e.hasMoreElements()) + { + String key = (String) e.nextElement(); + String[] values = req.getParameterValues(key); + if (values.length == 1) + { + m_options.put(key, values[0]); + } + else + { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < values.length; i++) + { + buf.append(values[i] + FORM_VALUE_DELIMETER); + } + m_options.put(key, buf.toString()); + } + } + } + + /** return the m_options as a string - obscure any "password" fields */ + public String optionsString() + { + StringBuffer buf = new StringBuffer(1024); + Enumeration e = m_options.keys(); + while (e.hasMoreElements()) + { + String key = (String) e.nextElement(); + Object o = m_options.getProperty(key); + if (o instanceof String) + { + buf.append(key); + buf.append("="); + if (key.equals("password")) + { + buf.append("*****"); + } + else + { + buf.append(o.toString()); + } + buf.append("&"); + } + } + + return buf.toString(); + } + } + +} Index: rwiki-access-tool/src/java/uk/ac/cam/caret/sakai/rwiki/access/WikiAccessServlet.java =================================================================== --- rwiki-access-tool/src/java/uk/ac/cam/caret/sakai/rwiki/access/WikiAccessServlet.java (revision 0) +++ rwiki-access-tool/src/java/uk/ac/cam/caret/sakai/rwiki/access/WikiAccessServlet.java (revision 0) @@ -0,0 +1,428 @@ +/********************************************************************************** + * $URL$ + * $Id$ + *********************************************************************************** + * + * Copyright (c) 2006 The Sakai Foundation. + * + * Licensed under the Educational Community License, Version 1.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/ecl1.php + * + * 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 uk.ac.cam.caret.sakai.rwiki.access; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Enumeration; +import java.util.Properties; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.sakaiproject.cheftool.VmServlet; +import org.sakaiproject.entity.api.EntityAccessOverloadException; +import org.sakaiproject.entity.api.EntityNotDefinedException; +import org.sakaiproject.entity.api.EntityPermissionException; +import org.sakaiproject.entity.api.EntityProducer; +import org.sakaiproject.entity.api.HttpAccess; +import org.sakaiproject.entity.api.Reference; +import org.sakaiproject.entity.cover.EntityManager; +import org.sakaiproject.tool.api.ActiveTool; +import org.sakaiproject.tool.api.Session; +import org.sakaiproject.tool.api.Tool; +import org.sakaiproject.tool.api.ToolException; +import org.sakaiproject.tool.cover.ActiveToolManager; +import org.sakaiproject.tool.cover.SessionManager; +import org.sakaiproject.util.BasicAuth; +import org.sakaiproject.util.ParameterParser; +import org.sakaiproject.util.Validator; +import org.sakaiproject.util.Web; + +/** + *

+ * Wiki extends access: all references are assumed to be under "/wiki/site" + *

+ * + * @author Sakai Software Development Team + */ +public class WikiAccessServlet extends VmServlet +{ + /** Our log (commons). */ + private static Log M_log = LogFactory.getLog(WikiAccessServlet.class); + + /** set to true when init'ed. */ + protected boolean m_ready = false; + + protected BasicAuth basicAuth = null; + + /** delimiter for form multiple values */ + protected static final String FORM_VALUE_DELIMETER = "^"; + + /** init thread - so we don't wait in the actual init() call */ + public class WikiServletInit extends Thread + { + /** + * construct and start the init activity + */ + public WikiServletInit() + { + m_ready = false; + start(); + } + + /** + * run the init + */ + public void run() + { + m_ready = true; + } + } + + /** + * initialize the AccessServlet servlet + * + * @param config + * the servlet config parameter + * @exception ServletException + * in case of difficulties + */ + public void init(ServletConfig config) throws ServletException + { + super.init(config); + startInit(); + basicAuth = new BasicAuth(); + basicAuth.init(); + + } + + /** + * Start the initialization process + */ + public void startInit() + { + new WikiServletInit(); + } + + /** + * Set active session according to sessionId parameter + */ + private void setSession( HttpServletRequest req ) + { + String sessionId = req.getParameter("session"); + if ( sessionId != null) + { + Session session = SessionManager.getSession(sessionId); + + if (session != null) + { + session.setActive(); + SessionManager.setCurrentSession(session); + } + } + } + + /** + * respond to an HTTP GET request + * + * @param req + * HttpServletRequest object with the client request + * @param res + * HttpServletResponse object back to the client + * @exception ServletException + * in case of difficulties + * @exception IOException + * in case of difficulties + */ + public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException + { + setSession(req); + dispatch(req, res); + } + + + /** + * handle get and post communication from the user + * + * @param req + * HttpServletRequest object with the client request + * @param res + * HttpServletResponse object back to the client + */ + public void dispatch(HttpServletRequest req, HttpServletResponse res) throws ServletException + { + ParameterParser params = (ParameterParser) req.getAttribute(ATTR_PARAMS); + + // get the path info + String path = params.getPath(); + if (path == null) path = ""; + + if (!m_ready) + { + sendError(res, HttpServletResponse.SC_SERVICE_UNAVAILABLE); + return; + } + + // pre-process the path + String origPath = path; + path = preProcessPath(path, req); + + // what is being requested? + Reference ref = EntityManager.newReference(path); + + // get the incoming information + WikiServletInfo info = newInfo(req); + + // let the entity producer handle it + try + { + // make sure we have a valid reference with an entity producer we can talk to + EntityProducer service = ref.getEntityProducer(); + if (service == null) throw new EntityNotDefinedException(ref.getReference()); + + // get the producer's HttpAccess helper, it might not support one + HttpAccess access = service.getHttpAccess(); + if (access == null) throw new EntityNotDefinedException(ref.getReference()); + + // let the helper do the work + access.handleAccess(req, res, ref, null); + } + catch (EntityNotDefinedException e) + { + // the request was not valid in some way + sendError(res, HttpServletResponse.SC_NOT_FOUND); + return; + } + catch (EntityPermissionException e) + { + // the end user does not have permission - offer a login if there is no user id yet established + // if not permitted, and the user is the anon user, let them login + if (SessionManager.getCurrentSessionUserId() == null) + { + try { + doLogin(req, res, origPath); + } catch ( IOException ioex ) {} + return; + } + + // otherwise reject the request + sendError(res, HttpServletResponse.SC_FORBIDDEN); + } + catch (EntityAccessOverloadException e) + { + M_log.info("dispatch(): ref: " + ref.getReference() + e); + sendError(res, HttpServletResponse.SC_SERVICE_UNAVAILABLE); + } + catch (Throwable e) + { + M_log.warn("dispatch(): exception: ", e); + sendError(res, HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + + finally + { + // log + if (M_log.isDebugEnabled()) + M_log.debug("from:" + req.getRemoteAddr() + " path:" + params.getPath() + " options: " + info.optionsString() + + " time: " + info.getElapsedTime()); + } + } + + + + /** + * respond to an HTTP POST request; only to handle the login process + * + * @param req + * HttpServletRequest object with the client request + * @param res + * HttpServletResponse object back to the client + * @exception ServletException + * in case of difficulties + * @exception IOException + * in case of difficulties + */ + public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException + { + // catch the login helper posts + String option = req.getPathInfo(); + String[] parts = option.split("/"); + if ((parts.length == 2) && ((parts[1].equals("login")))) + { + doLogin(req, res, null); + } + else + { + sendError(res, HttpServletResponse.SC_NOT_FOUND); + } + } + + /** + * Make any changes needed to the path before final "ref" processing. + * + * @param path + * The path from the request. + * @param req + * The request object. + * @return The path to use to make the Reference for further processing. + */ + protected String preProcessPath(String path, HttpServletRequest req) + { + // everything we work with is down the "content" part of the Sakai access URL space + + // if path is just "/", we don't really know if the request was to .../SERVLET or .../SERVLET/ - we want to preserve the trailing slash + // the request URI will tell us + if ("/".equals(path) && !(req.getRequestURI().endsWith("/"))) return "/wiki/site"; + + return "/wiki/site" + path; + } + + /** + * Make a redirect to the login url. + * + * @param req + * HttpServletRequest object with the client request. + * @param res + * HttpServletResponse object back to the client. + * @param path + * The current request path, set ONLY if we want this to be where to redirect the user after successfull login + * @throws IOException + */ + protected void doLogin(HttpServletRequest req, HttpServletResponse res, String path) throws ToolException, IOException + { + // if basic auth is valid do that + if ( basicAuth.doAuth(req,res) ) { + //System.err.println("BASIC Auth Request Sent to the Browser "); + return; + } + + + // get the Sakai session + Session session = SessionManager.getCurrentSession(); + + // set the return path for after login if needed (Note: in session, not tool session, special for Login helper) + if (path != null) + { + // where to go after + session.setAttribute(Tool.HELPER_DONE_URL, Web.returnUrl(req, Validator.escapeUrl(path))); + } + + // check that we have a return path set; might have been done earlier + if (session.getAttribute(Tool.HELPER_DONE_URL) == null) + { + M_log.warn("doLogin - proceeding with null HELPER_DONE_URL"); + } + + // map the request to the helper, leaving the path after ".../options" for the helper + ActiveTool tool = ActiveToolManager.getActiveTool("sakai.login"); + String context = req.getContextPath() + req.getServletPath() + "/login"; + tool.help(req, res, context, "/login"); + } + + protected void sendError(HttpServletResponse res, int code) + { + try + { + res.sendError(code); + } + catch (Throwable t) + { + M_log.warn("sendError: " + t); + } + } + + /** create the info */ + protected WikiServletInfo newInfo(HttpServletRequest req) + { + return new WikiServletInfo(req); + } + + public class WikiServletInfo + { + // elapsed time start + protected long m_startTime = System.currentTimeMillis(); + + public long getStartTime() + { + return m_startTime; + } + + public long getElapsedTime() + { + return System.currentTimeMillis() - m_startTime; + } + + // all properties from the request + protected Properties m_options = null; + + /** construct from the req */ + public WikiServletInfo(HttpServletRequest req) + { + m_options = new Properties(); + String type = req.getContentType(); + + Enumeration e = req.getParameterNames(); + while (e.hasMoreElements()) + { + String key = (String) e.nextElement(); + String[] values = req.getParameterValues(key); + if (values.length == 1) + { + m_options.put(key, values[0]); + } + else + { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < values.length; i++) + { + buf.append(values[i] + FORM_VALUE_DELIMETER); + } + m_options.put(key, buf.toString()); + } + } + } + + /** return the m_options as a string - obscure any "password" fields */ + public String optionsString() + { + StringBuffer buf = new StringBuffer(1024); + Enumeration e = m_options.keys(); + while (e.hasMoreElements()) + { + String key = (String) e.nextElement(); + Object o = m_options.getProperty(key); + if (o instanceof String) + { + buf.append(key); + buf.append("="); + if (key.equals("password")) + { + buf.append("*****"); + } + else + { + buf.append(o.toString()); + } + buf.append("&"); + } + } + + return buf.toString(); + } + } + +} Index: rwiki-access-tool/src/webapp/velocity.properties =================================================================== --- rwiki-access-tool/src/webapp/velocity.properties (revision 0) +++ rwiki-access-tool/src/webapp/velocity.properties (revision 0) @@ -0,0 +1,140 @@ +#---------------------------------------------------------------------------- +# These are the override settiongs over the default properties for the +# Velocity Runtime. +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# R U N T I M E L O G +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# default LogSystem to use: default: AvalonLogSystem +#---------------------------------------------------------------------------- + +###runtime.log.logsystem.class = org.apache.velocity.runtime.log.AvalonLogSystem,org.apache.velocity.runtime.log.SimpleLog4JLogSystem +runtime.log.logsystem.class = org.apache.velocity.runtime.log.NullLogSystem + +#--------------------------------------------------------------------------- +# This is the location of the Velocity Runtime log. +#---------------------------------------------------------------------------- + +###runtime.log = velocity_test.log + +#---------------------------------------------------------------------------- +# This controls if Runtime.error(), info() and warn() messages include the +# whole stack trace. The last property controls whether invalid references +# are logged. +#---------------------------------------------------------------------------- + +###runtime.log.error.stacktrace = false +###runtime.log.warn.stacktrace = false +###runtime.log.info.stacktrace = false +###runtime.log.invalid.reference = true + +#---------------------------------------------------------------------------- +# Configuration for the Log4JLogSystem. +# You must define the runtime.log.logsystem.class property to be: +# org.apache.velocity.runtime.log.Log4JLogSystem +# +# You must also include Log4J's .jar files into your classpath. They are +# included with the Velocity distribution in the build/lib directory. +# +# There are several different options that you can configure. +# Uncomment the ones that you want and also define their settings. +#---------------------------------------------------------------------------- +#runtime.log.logsystem.log4j.pattern=%d - %m%n +#runtime.log.logsystem.log4j.file.size=100000 +#runtime.log.logsystem.log4j.file.backups=1 +#runtime.log.logsystem.log4j.syslogd.host=my.syslog.server.com +#runtime.log.logsystem.log4j.syslogd.facility=LOG_DAEMON +#runtime.log.logsystem.log4j.remote.host=my.remote.server.com +#runtime.log.logsystem.log4j.remote.port=1099 +#runtime.log.logsystem.log4j.email.server=localhost +#runtime.log.logsystem.log4j.email.from=root@localhost +#runtime.log.logsystem.log4j.email.to=root@localhost +#runtime.log.logsystem.log4j.email.subject=Velocity Error Report +#runtime.log.logsystem.log4j.email.buffer.size=512 + +#---------------------------------------------------------------------------- +# T E M P L A T E E N C O D I N G +#---------------------------------------------------------------------------- + +# This encoding is needed to properly pass through international Unicode characters +input.encoding=UTF-8 +output.encoding=UTF-8 + +#---------------------------------------------------------------------------- +# F O R E A C H P R O P E R T I E S +#---------------------------------------------------------------------------- +# These properties control how the counter is accessed in the #foreach +# directive. By default the reference $velocityCount will be available +# in the body of the #foreach directive. The default starting value +# for this reference is 1. +#---------------------------------------------------------------------------- + +###directive.foreach.counter.name = velocityCount +###directive.foreach.counter.initial.value = 1 + +#---------------------------------------------------------------------------- +# I N C L U D E P R O P E R T I E S +#---------------------------------------------------------------------------- +# These are the properties that governed the way #include'd content +# is governed. +#---------------------------------------------------------------------------- + +###directive.include.output.errormsg.start = + +#---------------------------------------------------------------------------- +# P A R S E P R O P E R T I E S +#---------------------------------------------------------------------------- + +directive.parse.max.depth = 10 + +#---------------------------------------------------------------------------- +# T E M P L A T E L O A D E R S +#---------------------------------------------------------------------------- +# +# +#---------------------------------------------------------------------------- + +resource.loader = file + +file.resource.loader.description = Velocity File Resource Loader +file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader +file.resource.loader.path = .,WebRoot +file.resource.loader.cache = true +file.resource.loader.modificationCheckInterval = 0 + +#---------------------------------------------------------------------------- +# VELOCIMACRO PROPERTIES +#---------------------------------------------------------------------------- +# global : name of default global library. It is expected to be in the regular +# template path. You may remove it (either the file or this property) if +# you wish with no harm. +#---------------------------------------------------------------------------- +#velocimacro.library = VM_chef_library.vm + +###velocimacro.permissions.allow.inline = true +###velocimacro.permissions.allow.inline.to.replace.global = false +###velocimacro.permissions.allow.inline.local.scope = false + +###velocimacro.context.localscope = false + +#---------------------------------------------------------------------------- +# INTERPOLATION +#---------------------------------------------------------------------------- +# turn off and on interpolation of references and directives in string +# literals. ON by default :) +#---------------------------------------------------------------------------- +###runtime.interpolate.string.literals = true + + +#---------------------------------------------------------------------------- +# RESOURCE MANAGEMENT +#---------------------------------------------------------------------------- +# Allows alternative ResourceManager and ResourceCache implementations +# to be plugged in. +#---------------------------------------------------------------------------- +resource.manager.class = org.apache.velocity.runtime.resource.ResourceManagerImpl +resource.manager.cache.class = org.apache.velocity.runtime.resource.ResourceCacheImpl Index: rwiki-access-tool/src/webapp/velocity.properties =================================================================== --- rwiki-access-tool/src/webapp/velocity.properties (revision 0) +++ rwiki-access-tool/src/webapp/velocity.properties (revision 0) @@ -0,0 +1,140 @@ +#---------------------------------------------------------------------------- +# These are the override settiongs over the default properties for the +# Velocity Runtime. +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# R U N T I M E L O G +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# default LogSystem to use: default: AvalonLogSystem +#---------------------------------------------------------------------------- + +###runtime.log.logsystem.class = org.apache.velocity.runtime.log.AvalonLogSystem,org.apache.velocity.runtime.log.SimpleLog4JLogSystem +runtime.log.logsystem.class = org.apache.velocity.runtime.log.NullLogSystem + +#--------------------------------------------------------------------------- +# This is the location of the Velocity Runtime log. +#---------------------------------------------------------------------------- + +###runtime.log = velocity_test.log + +#---------------------------------------------------------------------------- +# This controls if Runtime.error(), info() and warn() messages include the +# whole stack trace. The last property controls whether invalid references +# are logged. +#---------------------------------------------------------------------------- + +###runtime.log.error.stacktrace = false +###runtime.log.warn.stacktrace = false +###runtime.log.info.stacktrace = false +###runtime.log.invalid.reference = true + +#---------------------------------------------------------------------------- +# Configuration for the Log4JLogSystem. +# You must define the runtime.log.logsystem.class property to be: +# org.apache.velocity.runtime.log.Log4JLogSystem +# +# You must also include Log4J's .jar files into your classpath. They are +# included with the Velocity distribution in the build/lib directory. +# +# There are several different options that you can configure. +# Uncomment the ones that you want and also define their settings. +#---------------------------------------------------------------------------- +#runtime.log.logsystem.log4j.pattern=%d - %m%n +#runtime.log.logsystem.log4j.file.size=100000 +#runtime.log.logsystem.log4j.file.backups=1 +#runtime.log.logsystem.log4j.syslogd.host=my.syslog.server.com +#runtime.log.logsystem.log4j.syslogd.facility=LOG_DAEMON +#runtime.log.logsystem.log4j.remote.host=my.remote.server.com +#runtime.log.logsystem.log4j.remote.port=1099 +#runtime.log.logsystem.log4j.email.server=localhost +#runtime.log.logsystem.log4j.email.from=root@localhost +#runtime.log.logsystem.log4j.email.to=root@localhost +#runtime.log.logsystem.log4j.email.subject=Velocity Error Report +#runtime.log.logsystem.log4j.email.buffer.size=512 + +#---------------------------------------------------------------------------- +# T E M P L A T E E N C O D I N G +#---------------------------------------------------------------------------- + +# This encoding is needed to properly pass through international Unicode characters +input.encoding=UTF-8 +output.encoding=UTF-8 + +#---------------------------------------------------------------------------- +# F O R E A C H P R O P E R T I E S +#---------------------------------------------------------------------------- +# These properties control how the counter is accessed in the #foreach +# directive. By default the reference $velocityCount will be available +# in the body of the #foreach directive. The default starting value +# for this reference is 1. +#---------------------------------------------------------------------------- + +###directive.foreach.counter.name = velocityCount +###directive.foreach.counter.initial.value = 1 + +#---------------------------------------------------------------------------- +# I N C L U D E P R O P E R T I E S +#---------------------------------------------------------------------------- +# These are the properties that governed the way #include'd content +# is governed. +#---------------------------------------------------------------------------- + +###directive.include.output.errormsg.start = + +#---------------------------------------------------------------------------- +# P A R S E P R O P E R T I E S +#---------------------------------------------------------------------------- + +directive.parse.max.depth = 10 + +#---------------------------------------------------------------------------- +# T E M P L A T E L O A D E R S +#---------------------------------------------------------------------------- +# +# +#---------------------------------------------------------------------------- + +resource.loader = file + +file.resource.loader.description = Velocity File Resource Loader +file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader +file.resource.loader.path = .,WebRoot +file.resource.loader.cache = true +file.resource.loader.modificationCheckInterval = 0 + +#---------------------------------------------------------------------------- +# VELOCIMACRO PROPERTIES +#---------------------------------------------------------------------------- +# global : name of default global library. It is expected to be in the regular +# template path. You may remove it (either the file or this property) if +# you wish with no harm. +#---------------------------------------------------------------------------- +#velocimacro.library = VM_chef_library.vm + +###velocimacro.permissions.allow.inline = true +###velocimacro.permissions.allow.inline.to.replace.global = false +###velocimacro.permissions.allow.inline.local.scope = false + +###velocimacro.context.localscope = false + +#---------------------------------------------------------------------------- +# INTERPOLATION +#---------------------------------------------------------------------------- +# turn off and on interpolation of references and directives in string +# literals. ON by default :) +#---------------------------------------------------------------------------- +###runtime.interpolate.string.literals = true + + +#---------------------------------------------------------------------------- +# RESOURCE MANAGEMENT +#---------------------------------------------------------------------------- +# Allows alternative ResourceManager and ResourceCache implementations +# to be plugged in. +#---------------------------------------------------------------------------- +resource.manager.class = org.apache.velocity.runtime.resource.ResourceManagerImpl +resource.manager.cache.class = org.apache.velocity.runtime.resource.ResourceCacheImpl Index: rwiki-access-tool/src/webapp/WEB-INF/web.xml =================================================================== --- rwiki-access-tool/src/webapp/WEB-INF/web.xml (revision 0) +++ rwiki-access-tool/src/webapp/WEB-INF/web.xml (revision 0) @@ -0,0 +1,56 @@ + + + sakai-wiki + Sakai Wiki + + + + sakai.request + org.sakaiproject.util.RequestFilter + + + + sakai.request + sakai.wiki + REQUEST + FORWARD + INCLUDE + + + + + + sakai.vm + + + org.sakaiproject.vm.VelocityServlet + + + properties + velocity.properties + + 1 + + + + + sakai.wiki + + + uk.ac.cam.caret.sakai.rwiki.access.WikiAccessServlet + + 1 + + + + + sakai.wiki + + + /* + + + + Index: rwiki-access-tool/src/webapp/WEB-INF/web.xml =================================================================== --- rwiki-access-tool/src/webapp/WEB-INF/web.xml (revision 0) +++ rwiki-access-tool/src/webapp/WEB-INF/web.xml (revision 0) @@ -0,0 +1,56 @@ + + + sakai-wiki + Sakai Wiki + + + + sakai.request + org.sakaiproject.util.RequestFilter + + + + sakai.request + sakai.wiki + REQUEST + FORWARD + INCLUDE + + + + + + sakai.vm + + + org.sakaiproject.vm.VelocityServlet + + + properties + velocity.properties + + 1 + + + + + sakai.wiki + + + uk.ac.cam.caret.sakai.rwiki.access.WikiAccessServlet + + 1 + + + + + sakai.wiki + + + /* + + + + Index: rwiki-impl/.classpath =================================================================== --- rwiki-impl/.classpath (revision 43807) +++ rwiki-impl/.classpath (working copy) @@ -54,5 +54,6 @@ +
Index: rwiki-impl/impl/project.xml =================================================================== --- rwiki-impl/impl/project.xml (revision 43807) +++ rwiki-impl/impl/project.xml (working copy) @@ -171,6 +171,11 @@ ${sakai.version} jar + + sakaiproject + sakai-alias-api + ${sakai.version} + sakaiproject sakai-sections-api Index: rwiki-impl/impl/src/java/uk/ac/cam/caret/sakai/rwiki/component/service/impl/BaseEntityHandlerImpl.java =================================================================== --- rwiki-impl/impl/src/java/uk/ac/cam/caret/sakai/rwiki/component/service/impl/BaseEntityHandlerImpl.java (revision 43807) +++ rwiki-impl/impl/src/java/uk/ac/cam/caret/sakai/rwiki/component/service/impl/BaseEntityHandlerImpl.java (working copy) @@ -23,9 +23,13 @@ import java.text.MessageFormat; +import org.sakaiproject.alias.api.AliasService; import org.sakaiproject.component.cover.ServerConfigurationService; import org.sakaiproject.entity.api.Entity; import org.sakaiproject.entity.api.Reference; +import org.sakaiproject.entity.cover.EntityManager; +import org.sakaiproject.exception.IdUnusedException; +import org.sakaiproject.site.api.SiteService; import uk.ac.cam.caret.sakai.rwiki.service.api.EntityHandler; @@ -60,7 +64,36 @@ private boolean available = true; + + /** Dependency: AliasService. */ + protected AliasService m_aliasService = null; + /** + * Dependency: AliasService. + * + * @param service + * The AliasService. + */ + public void setAliasService(AliasService service) + { + m_aliasService = service; + } + + /** Dependency: SiteService. */ + protected SiteService m_siteService = null; + + /** + * Dependency: SiteService. + * + * @param service + * The SiteService. + */ + public void setSiteService(SiteService service) + { + m_siteService = service; + } + + /** * {@inheritDoc} */ public void setReference(String majorType, Reference ref, String reference) @@ -140,7 +173,53 @@ { nextslash = firstslash; } - decoded.setContext(s.substring(0, nextslash)); + + String siteContext = s.substring(0, nextslash); + String context; + int slashIndex = siteContext.indexOf(Entity.SEPARATOR, 1); + if (slashIndex == -1) { + context = ""; + } else { + context = s.substring (slashIndex + 1, siteContext.length()); + } + + // recognize alias for site id - but if a site id exists that matches the requested site id, that's what we will use + if ((context != null) && (context.length() > 0)) + { + if ((m_aliasService != null) && (m_siteService != null) && (!m_siteService.siteExists(context))) + { + try + { + String target = m_aliasService.getTarget(context); + + // the code is taken and adapted from + // org.sakaiproject.content.impl.BaseContentService + // public boolean parseEntityReference(String reference, Reference ref) + Reference targetRef = EntityManager.newReference(target); + + // for a site reference + if (SiteService.APPLICATION_ID.equals(targetRef.getType())) + { + // use the ref's id, i.e. the site id + context = targetRef.getId(); + } + + // for mail archive reference + // TODO: taken from MailArchiveService.APPLICATION_ID to (fake) reduce a dependency -ggolden + else if ("sakai:mailarchive".equals(targetRef.getType())) + { + // use the ref's context as the site id + context = targetRef.getContext(); + } + } + catch (IdUnusedException noAlias) + { + } + } + siteContext = "/site/" + context; + } + + decoded.setContext(siteContext); if (nextslash == lastslash) { decoded.setContainer(Entity.SEPARATOR); Index: rwiki-impl/impl/src/java/uk/ac/cam/caret/sakai/rwiki/component/service/impl/PageVisits.java =================================================================== --- rwiki-impl/impl/src/java/uk/ac/cam/caret/sakai/rwiki/component/service/impl/PageVisits.java (revision 43807) +++ rwiki-impl/impl/src/java/uk/ac/cam/caret/sakai/rwiki/component/service/impl/PageVisits.java (working copy) @@ -28,6 +28,7 @@ import java.util.Stack; import org.sakaiproject.component.cover.ServerConfigurationService; +import org.sakaiproject.entity.api.Entity; import uk.ac.cam.caret.sakai.rwiki.service.api.RWikiObjectService; import uk.ac.cam.caret.sakai.rwiki.utils.NameHelper; @@ -39,6 +40,9 @@ { private static final int MAX_SIZE = 10; + /** Configuration: allow use of alias for site id in references. */ + protected boolean m_siteAlias = true; + private Stack s = new Stack(); public PageVisits() @@ -61,13 +65,23 @@ List l = new ArrayList(); if (s.size() > 0) { - String localSpace = NameHelper.localizeSpace(s.peek()); for (String pagename : s) { String[] pagespec = new String[2]; - pagespec[0] = ServerConfigurationService.getAccessUrl() + RWikiObjectService.REFERENCE_ROOT + encode(pagename) + + String localSpace = NameHelper.localizeSpace(pagename); + pagespec[1] = NameHelper.localizeName(pagename, localSpace); + + if (m_siteAlias) { + String localAliasSpace = NameHelper.aliasSpace(localSpace); + pagespec[0] = RWikiObjectService.REFERENCE_ROOT + localAliasSpace + + Entity.SEPARATOR + + encode(pagespec[1]) + "." + type; - pagespec[1] = NameHelper.localizeName(pagename, localSpace); + } else { + pagespec[0] = ServerConfigurationService.getAccessUrl() + RWikiObjectService.REFERENCE_ROOT + encode(pagename) + + "." + type; + } l.add(pagespec); } } Index: rwiki-impl/impl/src/java/uk/ac/cam/caret/sakai/rwiki/component/service/impl/XSLTEntityHandler.java =================================================================== --- rwiki-impl/impl/src/java/uk/ac/cam/caret/sakai/rwiki/component/service/impl/XSLTEntityHandler.java (revision 43807) +++ rwiki-impl/impl/src/java/uk/ac/cam/caret/sakai/rwiki/component/service/impl/XSLTEntityHandler.java (working copy) @@ -44,7 +44,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.xalan.templates.OutputProperties; import org.apache.xml.serializer.OutputPropertiesFactory; import org.apache.xml.serializer.Serializer; import org.apache.xml.serializer.SerializerFactory; @@ -153,6 +152,10 @@ private SerializerFactory serializerFactory; + /** Configuration: allow use of alias for site id in references. */ + protected boolean m_siteAlias = true; + + private Object load(ComponentManager cm, String name) { Object o = cm.get(name); @@ -646,8 +649,18 @@ public String render(RWikiObject rwo) { String localSpace = NameHelper.localizeSpace(rwo.getName(), rwo.getRealm()); - ComponentPageLinkRenderImpl plr = new ComponentPageLinkRenderImpl(localSpace); + // use mail archive aliasing here to render links with short URL + // localSpace pattern: /site/siteId + String localAliasSpace; + if (m_siteAlias) { + localAliasSpace = NameHelper.aliasSpace(localSpace); + } else { + localAliasSpace = localSpace; + } + + ComponentPageLinkRenderImpl plr = new ComponentPageLinkRenderImpl(localAliasSpace); + plr.setAnchorURLFormat(anchorLinkFormat); plr.setStandardURLFormat(standardLinkFormat); plr.setUrlFormat(hrefTagFormat); Index: rwiki-impl/pack/src/webapp/WEB-INF/coreServiceComponents.xml =================================================================== --- rwiki-impl/pack/src/webapp/WEB-INF/coreServiceComponents.xml (revision 43807) +++ rwiki-impl/pack/src/webapp/WEB-INF/coreServiceComponents.xml (working copy) @@ -139,8 +139,8 @@ Failed To generate Stack Trace : {0} Error encounvered performing transform : {0} \n {1} /wiki - /access/wiki{0}.html#{1} - /access/wiki{0}.html + /wiki{0}.html#{1} + /wiki{0}.html <a href="{0}" >{1}</a> /wiki/ <a href="{0}html" target="feeds"><img src="/library/image/sakai/html.gif" border="0" alt="Html" /> Public View </a> @@ -164,6 +164,8 @@ no + + Failed To generate Stack Trace : {0} Error encounvered performing transform : {0} \n {1} /wiki - /access/wiki{0}.html#{1} - /access/wiki{0}.html + /wiki{0}.html#{1} + /wiki{0}.html <a href="{0}" >{1}</a> /wiki/ <a href="{0}pdf" target="feeds"><img src="/library/image/sakai/pdf.gif" border="0" alt="PDF" />PDF</a> @@ -192,6 +194,8 @@ uk.ac.cam.caret.sakai.rwiki.component.service.impl.FOP2PDFSerializer + + Failed To generate Stack Trace : {0} Error encounvered performing transform : {0} \n {1} /wiki - /access/wiki{0}.html#{1} - /access/wiki{0}.html + /wiki{0}.html#{1} + /wiki{0}.html <a href="{0}" >{1}</a> /wiki/ <a href="{0}rtf" target="feeds"><img src="/library/image/sakai/word.gif" border="0" alt="RTF" /></a> @@ -221,6 +225,8 @@ uk.ac.cam.caret.sakai.rwiki.component.service.impl.FOP2RTFSerializer + + - + Index: rwiki-util/.classpath =================================================================== --- rwiki-util/.classpath (revision 43807) +++ rwiki-util/.classpath (working copy) @@ -17,5 +17,8 @@ + + + Index: rwiki-util/util/project.xml =================================================================== --- rwiki-util/util/project.xml (revision 43807) +++ rwiki-util/util/project.xml (working copy) @@ -47,7 +47,19 @@ + sakaiproject + sakai-alias-api + ${sakai.version} + + sakaiproject + sakai-site-api + ${sakai.version} + jar + + + + sakaiproject sakai-entity-api ${sakai.version} jar Index: rwiki-util/util/src/java/uk/ac/cam/caret/sakai/rwiki/utils/NameHelper.java =================================================================== --- rwiki-util/util/src/java/uk/ac/cam/caret/sakai/rwiki/utils/NameHelper.java (revision 43807) +++ rwiki-util/util/src/java/uk/ac/cam/caret/sakai/rwiki/utils/NameHelper.java (working copy) @@ -22,10 +22,17 @@ package uk.ac.cam.caret.sakai.rwiki.utils; import java.nio.CharBuffer; +import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.sakaiproject.alias.api.AliasEdit; +import org.sakaiproject.alias.cover.AliasService; +import org.sakaiproject.entity.api.Entity; +import org.sakaiproject.site.cover.SiteService; +import org.sakaiproject.util.StringUtil; + public class NameHelper { @@ -304,4 +311,33 @@ return globalPageName.substring(0, index); } + public static String aliasSpace (final String localSpace) + { + String localAliasSpace = localSpace; + + String parts[] = StringUtil.split (localSpace, Entity.SEPARATOR); + + String siteId = parts[2]; + // recognize alias for site id - but if a site id exists that matches the requested site id, that's what we will use + if ((siteId != null) && (siteId.length() > 0)) + { + List target = AliasService.getAliases( + "/mailarchive/channel/" + siteId + "/main"); + + if (!target.isEmpty()) { + // take the first alias only + AliasEdit alias = (AliasEdit) target.get(0); + siteId = alias.getId(); + + // if there is no a site id exists that matches the alias name + if (!SiteService.siteExists(siteId)) + { + localAliasSpace = "/" + siteId; + } + } + } + + return localAliasSpace; + } + }