Index: jspwiki-war/pom.xml =================================================================== --- jspwiki-war/pom.xml (revision 1655294) +++ jspwiki-war/pom.xml (working copy) @@ -99,6 +99,11 @@ + com.google.code.gson + gson + + + org.jvnet.hudson org.suigeneris.jrcs.diff Index: jspwiki-war/src/main/java/org/apache/wiki/ajax/AjaxUtil.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/ajax/AjaxUtil.java (revision 0) +++ jspwiki-war/src/main/java/org/apache/wiki/ajax/AjaxUtil.java (working copy) @@ -0,0 +1,70 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache 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.apache.org/licenses/LICENSE-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.apache.wiki.ajax; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; + +import org.apache.commons.lang.StringUtils; + +import com.google.gson.Gson; + +public class AjaxUtil extends HttpServlet { + private static final long serialVersionUID = 3170439306358345408L; + private static Gson gson = new Gson(); + + public static String toJson(Object input) { + String result = ""; + if (input != null) { + result = gson.toJson(input); + } + return result; + } + + public static String getNextPathPart(String path, String lastPart) throws ServletException { + String result = null; + if (StringUtils.isBlank(path)) { + return result; + } + if (!lastPart.endsWith("/")) { + lastPart += "/"; + } + int index = path.indexOf(lastPart); + if (index<0) { + throw new ServletException("Invalid path provided " + path + " does not contain '" + lastPart + "'"); + } + path = path.substring(index+lastPart.length()); + index = path.indexOf("/"); + if (index == -1) { + index = path.indexOf("#"); + if (index == -1) { + index = path.indexOf("?"); + } + } + if (index == -1) { + result = path; + } + else { + result = path.substring(0,index); + } + + return result; + } + +} Property changes on: jspwiki-war/src/main/java/org/apache/wiki/ajax/AjaxUtil.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxDispatcherServlet.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxDispatcherServlet.java (revision 0) +++ jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxDispatcherServlet.java (working copy) @@ -0,0 +1,204 @@ +/* + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache 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.apache.org/licenses/LICENSE-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.apache.wiki.ajax; + +import java.io.IOException; +import java.security.Permission; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.apache.wiki.WikiEngine; +import org.apache.wiki.WikiSession; +import org.apache.wiki.auth.permissions.PagePermission; +import org.apache.wiki.util.TextUtil; + +/** + * This provides a simple ajax servlet for handling /ajax/ requests. + * HttpServlet classes need to be registered using {@link WikiAjaxDispatcherServlet.registerServlet(HttpServlet)} + * + * @since 2.10.2-svn10 + */ +public class WikiAjaxDispatcherServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + private static Map ajaxServlets = new HashMap(); + static final Logger log = Logger.getLogger(WikiAjaxDispatcherServlet.class.getName()); + private String PATH_AJAX = "/ajax/"; + + /** + * {@inheritDoc} + */ + public void init(ServletConfig config) + throws ServletException { + super.init(config); + WikiEngine e = WikiEngine.getInstance(config); + PATH_AJAX = "/"+TextUtil.getStringProperty(e.getWikiProperties(), "jspwiki.ajax.url.prefix", "ajax")+"/"; + log.info("WikiAjaxDispatcherServlet initialized."); + } + + /** + * Register a servlet using the class simple name as the alias + */ + public static void registerServlet(WikiAjaxServlet servlet) { + registerServlet(servlet.getServletMapping(),servlet); + } + + /** + * Register a servlet with an alias, using the default permission {@link PagePermission.VIEW}. + */ + public static void registerServlet(String alias, WikiAjaxServlet servlet) { + registerServlet(alias, servlet, PagePermission.VIEW); + } + + public static void registerServlet(String alias, WikiAjaxServlet servlet, Permission perm) { + log.info("WikiAjaxDispatcherServlet registering "+alias+"="+servlet+" perm="+perm); + ajaxServlets.put(alias,new AjaxServletContainer(alias, servlet, perm)); + } + + /** + * Calls {@link this.performAction} + */ + public void doPost(HttpServletRequest req, HttpServletResponse res) + throws IOException, ServletException { + performAction(req,res); + } + + /** + * Calls {@link this.performAction} + */ + public void doGet(HttpServletRequest req, HttpServletResponse res) + throws IOException, ServletException { + performAction(req,res); + } + + /** + * The main method which get the requestURI "/ajax/", gets the + * {@link this.getServletName} and finds the servlet using {@link this.findServletByName}. + * It then calls servlet.service(). + * @param req the inbound request + * @param res the outbound response + * @throws IOException + * @throws ServletException if no registered servlet can be found + */ + private void performAction(HttpServletRequest req, HttpServletResponse res) + throws IOException, ServletException { + String path = req.getRequestURI(); + String servletName = getServletName(path); + if (servletName!=null) { + AjaxServletContainer container = findServletContainer(servletName); + if (container != null) { + WikiAjaxServlet servlet = container.servlet; + if ( validatePermission(req,container) ) { + String actionName = AjaxUtil.getNextPathPart(req.getRequestURI(), servlet.getServletMapping()); + log.debug("actionName="+actionName); + Object params = req.getAttribute("params"); + log.debug("params="+params); + List paramValues = new ArrayList(); + if (params != null) { + if (params instanceof String) { + String paramString = (String)params; + if (StringUtils.isNotBlank(paramString)) { + paramString = paramString.trim(); + paramValues = Arrays.asList(paramString.split(",")); + } else if (params instanceof Collection) { + for(Object o : (Collection)params) { + if (o != null) { + paramValues.add(o.toString().trim()); + } + } + } + } + } + servlet.service(req, res, actionName, paramValues); + } else { + log.warn("Servlet container "+container+" not authorised. Permission required."); + } + } else { + log.error("No registered class for servletName=" + servletName + " in path=" + path); + throw new ServletException("No registered class for servletName=" + servletName); + } + } + } + + private boolean validatePermission(HttpServletRequest req, AjaxServletContainer container) { + WikiEngine e = WikiEngine.getInstance(req.getSession().getServletContext(), null); + boolean valid = false; + if (container != null) { + valid = e.getAuthorizationManager().checkPermission(WikiSession.getWikiSession(e, req), container.permission); + } + return valid; + } + + /** + * Get the name of the servlet given the requestURI. + * @param path The requestURI, which must contains "/ajax/" in the path + * @return The ServletName for the requestURI, or null + * @throws ServletException if the path is invalid + */ + public String getServletName(String path) throws ServletException { + return AjaxUtil.getNextPathPart(path, PATH_AJAX); + } + + /** + * Find the servlet as registered in {@link WikiAjaxDispatcherServlet.register}. + * + * @param servletName the name of the servlet from {@link this.getServletName} + * @return The first servlet found, or null. + */ + public AjaxServletContainer findServletContainer(String servletAlias) { + return ajaxServlets.get(servletAlias); + } + + public WikiAjaxServlet findServletByName(String servletAlias) { + AjaxServletContainer container = ajaxServlets.get(servletAlias); + if (container != null) { + return container.servlet; + } + return null; + } + + private static class AjaxServletContainer { + String alias; + WikiAjaxServlet servlet; + Permission permission; + + public AjaxServletContainer(String alias, WikiAjaxServlet servlet, Permission permission) { + this.alias = alias; + this.servlet = servlet; + this.permission = permission; + } + + public String toString() { + return getClass().getSimpleName()+" "+alias+"="+servlet.getClass().getSimpleName()+" permission="+permission; + } + } + +} Property changes on: jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxDispatcherServlet.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxServlet.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxServlet.java (revision 0) +++ jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxServlet.java (working copy) @@ -0,0 +1,16 @@ +package org.apache.wiki.ajax; + +import java.io.IOException; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public interface WikiAjaxServlet { + + public String getServletMapping(); + + public void service(HttpServletRequest request, HttpServletResponse response, String actionName, List params) throws ServletException, IOException; + +} Property changes on: jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxServlet.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jspwiki-war/src/main/java/org/apache/wiki/ajax/AjaxUtil.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/ajax/AjaxUtil.java (revision 0) +++ jspwiki-war/src/main/java/org/apache/wiki/ajax/AjaxUtil.java (working copy) @@ -0,0 +1,70 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache 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.apache.org/licenses/LICENSE-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.apache.wiki.ajax; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; + +import org.apache.commons.lang.StringUtils; + +import com.google.gson.Gson; + +public class AjaxUtil extends HttpServlet { + private static final long serialVersionUID = 3170439306358345408L; + private static Gson gson = new Gson(); + + public static String toJson(Object input) { + String result = ""; + if (input != null) { + result = gson.toJson(input); + } + return result; + } + + public static String getNextPathPart(String path, String lastPart) throws ServletException { + String result = null; + if (StringUtils.isBlank(path)) { + return result; + } + if (!lastPart.endsWith("/")) { + lastPart += "/"; + } + int index = path.indexOf(lastPart); + if (index<0) { + throw new ServletException("Invalid path provided " + path + " does not contain '" + lastPart + "'"); + } + path = path.substring(index+lastPart.length()); + index = path.indexOf("/"); + if (index == -1) { + index = path.indexOf("#"); + if (index == -1) { + index = path.indexOf("?"); + } + } + if (index == -1) { + result = path; + } + else { + result = path.substring(0,index); + } + + return result; + } + +} Property changes on: jspwiki-war/src/main/java/org/apache/wiki/ajax/AjaxUtil.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxDispatcherServlet.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxDispatcherServlet.java (revision 0) +++ jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxDispatcherServlet.java (working copy) @@ -0,0 +1,204 @@ +/* + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache 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.apache.org/licenses/LICENSE-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.apache.wiki.ajax; + +import java.io.IOException; +import java.security.Permission; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.apache.wiki.WikiEngine; +import org.apache.wiki.WikiSession; +import org.apache.wiki.auth.permissions.PagePermission; +import org.apache.wiki.util.TextUtil; + +/** + * This provides a simple ajax servlet for handling /ajax/ requests. + * HttpServlet classes need to be registered using {@link WikiAjaxDispatcherServlet.registerServlet(HttpServlet)} + * + * @since 2.10.2-svn10 + */ +public class WikiAjaxDispatcherServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + private static Map ajaxServlets = new HashMap(); + static final Logger log = Logger.getLogger(WikiAjaxDispatcherServlet.class.getName()); + private String PATH_AJAX = "/ajax/"; + + /** + * {@inheritDoc} + */ + public void init(ServletConfig config) + throws ServletException { + super.init(config); + WikiEngine e = WikiEngine.getInstance(config); + PATH_AJAX = "/"+TextUtil.getStringProperty(e.getWikiProperties(), "jspwiki.ajax.url.prefix", "ajax")+"/"; + log.info("WikiAjaxDispatcherServlet initialized."); + } + + /** + * Register a servlet using the class simple name as the alias + */ + public static void registerServlet(WikiAjaxServlet servlet) { + registerServlet(servlet.getServletMapping(),servlet); + } + + /** + * Register a servlet with an alias, using the default permission {@link PagePermission.VIEW}. + */ + public static void registerServlet(String alias, WikiAjaxServlet servlet) { + registerServlet(alias, servlet, PagePermission.VIEW); + } + + public static void registerServlet(String alias, WikiAjaxServlet servlet, Permission perm) { + log.info("WikiAjaxDispatcherServlet registering "+alias+"="+servlet+" perm="+perm); + ajaxServlets.put(alias,new AjaxServletContainer(alias, servlet, perm)); + } + + /** + * Calls {@link this.performAction} + */ + public void doPost(HttpServletRequest req, HttpServletResponse res) + throws IOException, ServletException { + performAction(req,res); + } + + /** + * Calls {@link this.performAction} + */ + public void doGet(HttpServletRequest req, HttpServletResponse res) + throws IOException, ServletException { + performAction(req,res); + } + + /** + * The main method which get the requestURI "/ajax/", gets the + * {@link this.getServletName} and finds the servlet using {@link this.findServletByName}. + * It then calls servlet.service(). + * @param req the inbound request + * @param res the outbound response + * @throws IOException + * @throws ServletException if no registered servlet can be found + */ + private void performAction(HttpServletRequest req, HttpServletResponse res) + throws IOException, ServletException { + String path = req.getRequestURI(); + String servletName = getServletName(path); + if (servletName!=null) { + AjaxServletContainer container = findServletContainer(servletName); + if (container != null) { + WikiAjaxServlet servlet = container.servlet; + if ( validatePermission(req,container) ) { + String actionName = AjaxUtil.getNextPathPart(req.getRequestURI(), servlet.getServletMapping()); + log.debug("actionName="+actionName); + Object params = req.getAttribute("params"); + log.debug("params="+params); + List paramValues = new ArrayList(); + if (params != null) { + if (params instanceof String) { + String paramString = (String)params; + if (StringUtils.isNotBlank(paramString)) { + paramString = paramString.trim(); + paramValues = Arrays.asList(paramString.split(",")); + } else if (params instanceof Collection) { + for(Object o : (Collection)params) { + if (o != null) { + paramValues.add(o.toString().trim()); + } + } + } + } + } + servlet.service(req, res, actionName, paramValues); + } else { + log.warn("Servlet container "+container+" not authorised. Permission required."); + } + } else { + log.error("No registered class for servletName=" + servletName + " in path=" + path); + throw new ServletException("No registered class for servletName=" + servletName); + } + } + } + + private boolean validatePermission(HttpServletRequest req, AjaxServletContainer container) { + WikiEngine e = WikiEngine.getInstance(req.getSession().getServletContext(), null); + boolean valid = false; + if (container != null) { + valid = e.getAuthorizationManager().checkPermission(WikiSession.getWikiSession(e, req), container.permission); + } + return valid; + } + + /** + * Get the name of the servlet given the requestURI. + * @param path The requestURI, which must contains "/ajax/" in the path + * @return The ServletName for the requestURI, or null + * @throws ServletException if the path is invalid + */ + public String getServletName(String path) throws ServletException { + return AjaxUtil.getNextPathPart(path, PATH_AJAX); + } + + /** + * Find the servlet as registered in {@link WikiAjaxDispatcherServlet.register}. + * + * @param servletName the name of the servlet from {@link this.getServletName} + * @return The first servlet found, or null. + */ + public AjaxServletContainer findServletContainer(String servletAlias) { + return ajaxServlets.get(servletAlias); + } + + public WikiAjaxServlet findServletByName(String servletAlias) { + AjaxServletContainer container = ajaxServlets.get(servletAlias); + if (container != null) { + return container.servlet; + } + return null; + } + + private static class AjaxServletContainer { + String alias; + WikiAjaxServlet servlet; + Permission permission; + + public AjaxServletContainer(String alias, WikiAjaxServlet servlet, Permission permission) { + this.alias = alias; + this.servlet = servlet; + this.permission = permission; + } + + public String toString() { + return getClass().getSimpleName()+" "+alias+"="+servlet.getClass().getSimpleName()+" permission="+permission; + } + } + +} Property changes on: jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxDispatcherServlet.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxServlet.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxServlet.java (revision 0) +++ jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxServlet.java (working copy) @@ -0,0 +1,16 @@ +package org.apache.wiki.ajax; + +import java.io.IOException; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public interface WikiAjaxServlet { + + public String getServletMapping(); + + public void service(HttpServletRequest request, HttpServletResponse response, String actionName, List params) throws ServletException, IOException; + +} Property changes on: jspwiki-war/src/main/java/org/apache/wiki/ajax/WikiAjaxServlet.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jspwiki-war/src/main/java/org/apache/wiki/auth/user/DefaultUserProfile.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/auth/user/DefaultUserProfile.java (revision 1655294) +++ jspwiki-war/src/main/java/org/apache/wiki/auth/user/DefaultUserProfile.java (working copy) @@ -39,25 +39,25 @@ private static final String WHITESPACE = "\\s"; - private Map m_attributes = new HashMap(); + private Map attributes = new HashMap(); - private Date m_created = null; + private Date created = null; - private String m_email = null; + private String email = null; - private String m_fullname = null; + private String fullname = null; - private Date m_lockExpiry = null; + private Date lockExpiry = null; - private String m_loginName = null; + private String loginName = null; - private Date m_modified = null; + private Date modified = null; - private String m_password = null; + private String password = null; - private String m_uid = null; + private String uid = null; - private String m_wikiname = null; + private String wikiname = null; /** * Private constructor to prevent direct instantiation. @@ -86,9 +86,9 @@ if ( ( o != null ) && ( o instanceof UserProfile ) ) { DefaultUserProfile u = (DefaultUserProfile) o; - return same( m_fullname, u.m_fullname ) && same( m_password, u.m_password ) - && same( m_loginName, u.m_loginName ) && same(StringUtils.lowerCase( m_email ), StringUtils.lowerCase( u.m_email ) ) && same( m_wikiname, - u.m_wikiname ); + return same( fullname, u.fullname ) && same( password, u.password ) + && same( loginName, u.loginName ) && same(StringUtils.lowerCase( email ), StringUtils.lowerCase( u.email ) ) && same( wikiname, + u.wikiname ); } return false; @@ -96,11 +96,11 @@ public int hashCode() { - return (m_fullname != null ? m_fullname.hashCode() : 0) ^ - (m_password != null ? m_password.hashCode() : 0) ^ - (m_loginName != null ? m_loginName.hashCode() : 0) ^ - (m_wikiname != null ? m_wikiname.hashCode() : 0) ^ - (m_email != null ? StringUtils.lowerCase( m_email ).hashCode() : 0); + return (fullname != null ? fullname.hashCode() : 0) ^ + (password != null ? password.hashCode() : 0) ^ + (loginName != null ? loginName.hashCode() : 0) ^ + (wikiname != null ? wikiname.hashCode() : 0) ^ + (email != null ? StringUtils.lowerCase( email ).hashCode() : 0); } /** @@ -110,7 +110,7 @@ */ public Date getCreated() { - return m_created; + return created; } /** @@ -119,7 +119,7 @@ */ public String getEmail() { - return m_email; + return email; } /** @@ -128,7 +128,7 @@ */ public String getFullname() { - return m_fullname; + return fullname; } /** @@ -138,7 +138,7 @@ */ public Date getLastModified() { - return m_modified; + return modified; } /** @@ -147,7 +147,7 @@ */ public String getLoginName() { - return m_loginName; + return loginName; } /** @@ -161,7 +161,7 @@ */ public String getPassword() { - return m_password; + return password; } /** @@ -170,7 +170,7 @@ */ public String getWikiName() { - return m_wikiname; + return wikiname; } /** @@ -182,7 +182,7 @@ */ public boolean isNew() { - return m_modified == null; + return modified == null; } /** @@ -191,7 +191,7 @@ */ public void setCreated(Date date) { - m_created = date; + created = date; } /** @@ -200,7 +200,7 @@ */ public void setEmail( String email ) { - m_email = email; + this.email = email; } /** @@ -209,12 +209,12 @@ */ public void setFullname( String arg ) { - m_fullname = arg; + fullname = arg; // Compute wiki name - if ( m_fullname != null ) + if ( fullname != null ) { - m_wikiname = m_fullname.replaceAll(WHITESPACE, EMPTY_STRING); + wikiname = fullname.replaceAll(WHITESPACE, EMPTY_STRING); } } @@ -225,7 +225,7 @@ */ public void setLastModified( Date date ) { - m_modified = date; + modified = date; } /** @@ -238,7 +238,7 @@ */ public void setLoginName( String name ) { - m_loginName = name; + loginName = name; } /** @@ -253,7 +253,7 @@ */ public void setPassword( String arg ) { - m_password = arg; + password = arg; } /** @@ -304,7 +304,7 @@ */ public Map getAttributes() { - return m_attributes; + return attributes; } /** @@ -312,7 +312,7 @@ */ public Date getLockExpiry() { - return isLocked() ? m_lockExpiry : null; + return isLocked() ? lockExpiry : null; } /** @@ -320,7 +320,7 @@ */ public String getUid() { - return m_uid; + return uid; } /** @@ -328,12 +328,12 @@ */ public boolean isLocked() { - boolean locked = m_lockExpiry != null && System.currentTimeMillis() < m_lockExpiry.getTime(); + boolean locked = lockExpiry != null && System.currentTimeMillis() < lockExpiry.getTime(); // Clear the lock if it's expired already - if ( !locked && m_lockExpiry != null ) + if ( !locked && lockExpiry != null ) { - m_lockExpiry = null; + lockExpiry = null; } return locked; } @@ -343,7 +343,7 @@ */ public void setLockExpiry( Date expiry ) { - m_lockExpiry = expiry; + this.lockExpiry = expiry; } /** @@ -351,6 +351,6 @@ */ public void setUid( String uid ) { - m_uid = uid; + this.uid = uid; } } Index: jspwiki-war/src/main/java/org/apache/wiki/auth/UserManager.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/auth/UserManager.java (revision 1655294) +++ jspwiki-war/src/main/java/org/apache/wiki/auth/UserManager.java (working copy) @@ -18,6 +18,7 @@ */ package org.apache.wiki.auth; +import java.io.IOException; import java.security.Permission; import java.security.Principal; import java.text.MessageFormat; @@ -30,7 +31,9 @@ import javax.mail.MessagingException; import javax.mail.internet.AddressException; +import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; @@ -37,6 +40,9 @@ import org.apache.wiki.WikiContext; import org.apache.wiki.WikiEngine; import org.apache.wiki.WikiSession; +import org.apache.wiki.ajax.AjaxUtil; +import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; +import org.apache.wiki.ajax.WikiAjaxServlet; import org.apache.wiki.api.engine.FilterManager; import org.apache.wiki.api.exceptions.NoRequiredPropertyException; import org.apache.wiki.api.exceptions.WikiException; @@ -53,8 +59,6 @@ import org.apache.wiki.filters.SpamFilter; import org.apache.wiki.i18n.InternationalizationManager; import org.apache.wiki.preferences.Preferences; -import org.apache.wiki.rpc.RPCCallable; -import org.apache.wiki.rpc.json.JSONRPCManager; import org.apache.wiki.ui.InputValidator; import org.apache.wiki.util.ClassUtil; import org.apache.wiki.util.MailUtil; @@ -97,6 +101,8 @@ protected static final String PREFS_FULL_NAME = "prefs.fullname"; protected static final String PREFS_EMAIL = "prefs.email"; + public static final String JSON_USERS = "users"; + // private static final String PROP_ACLMANAGER = "jspwiki.aclManager"; /** Associates wiki sessions with profiles */ @@ -125,7 +131,8 @@ // TODO: it would be better if we did this in PageManager directly addWikiEventListener( engine.getPageManager() ); - JSONRPCManager.registerGlobalObject( "users", new JSONUserModule(this), new AllPermission(null) ); + //TODO: Replace with custom annotations. See JSPWIKI-566 + WikiAjaxDispatcherServlet.registerServlet( JSON_USERS, new JSONUserModule(this), new AllPermission(null)); } /** @@ -843,7 +850,7 @@ WikiEventManager.fireEvent(this,new WikiSecurityEvent(session,type,profile)); } } - + /** * Implements the JSON API for usermanager. *

@@ -851,9 +858,9 @@ * this gets reinstalled to the session when JSPWiki starts. This means * that it's not actually necessary to save anything. */ - public static final class JSONUserModule implements RPCCallable + public static final class JSONUserModule implements WikiAjaxServlet { - private volatile UserManager m_manager; + private volatile UserManager m_manager; /** * Create a new JSONUserModule. @@ -864,6 +871,27 @@ m_manager = mgr; } + @Override + public String getServletMapping() { + return JSON_USERS; + } + + public void service(HttpServletRequest req, HttpServletResponse resp, String actionName, List params) throws ServletException, IOException { + try { + String uid = null; + if (params.size()<1) { + uid = params.get(1); + } + log.debug("uid="+uid); + if (StringUtils.isNotBlank(uid)) { + UserProfile prof = getUserInfo(uid); + resp.getWriter().write(AjaxUtil.toJson(prof)); + } + } catch (NoSuchPrincipalException e) { + throw new ServletException(e); + } + } + /** * Directly returns the UserProfile object attached to an uid. * Index: jspwiki-war/src/main/java/org/apache/wiki/plugin/DefaultPluginManager.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/plugin/DefaultPluginManager.java (revision 1655294) +++ jspwiki-war/src/main/java/org/apache/wiki/plugin/DefaultPluginManager.java (working copy) @@ -20,6 +20,7 @@ package org.apache.wiki.plugin; import org.apache.commons.lang.ClassUtils; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.oro.text.regex.MalformedPatternException; import org.apache.oro.text.regex.MatchResult; @@ -29,9 +30,10 @@ import org.apache.oro.text.regex.Perl5Compiler; import org.apache.oro.text.regex.Perl5Matcher; import org.apache.wiki.InternalWikiException; -import org.apache.wiki.WikiAjaxDispatcherServlet; import org.apache.wiki.WikiContext; import org.apache.wiki.WikiEngine; +import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; +import org.apache.wiki.ajax.WikiAjaxServlet; import org.apache.wiki.api.engine.PluginManager; import org.apache.wiki.api.exceptions.PluginException; import org.apache.wiki.api.plugin.InitializablePlugin; @@ -546,7 +548,7 @@ m_pluginClassMap.put( name, pluginClass ); } - pluginClass.initializePlugin( m_engine , m_searchPath, m_externalJars); + pluginClass.initializePlugin( pluginClass, m_engine , m_searchPath, m_externalJars); } private void registerPlugins() { @@ -580,6 +582,7 @@ private String m_className; private String m_alias; + private String m_ajaxAlias; private Class m_clazz; private boolean m_initialized = false; @@ -611,7 +614,7 @@ * @param searchPath A List of Strings, containing different package names. * @param externalJars the list of external jars to search */ - protected void initializePlugin( WikiEngine engine , List searchPath, List externalJars) { + protected void initializePlugin( WikiPluginInfo info, WikiEngine engine , List searchPath, List externalJars) { if( !m_initialized ) { // This makes sure we only try once per class, even if init fails. m_initialized = true; @@ -621,8 +624,12 @@ if( p instanceof InitializablePlugin ) { ( ( InitializablePlugin )p ).initialize( engine ); } - if( p instanceof HttpServlet ) { - WikiAjaxDispatcherServlet.register( (HttpServlet) p ); + if( p instanceof WikiAjaxServlet ) { + WikiAjaxDispatcherServlet.registerServlet( (WikiAjaxServlet) p ); + String ajaxAlias = info.getAjaxAlias(); + if (StringUtils.isNotBlank(ajaxAlias)) { + WikiAjaxDispatcherServlet.registerServlet( info.getAjaxAlias(), (WikiAjaxServlet) p ); + } } } catch( Exception e ) { log.info( "Cannot initialize plugin " + m_className, e ); @@ -637,6 +644,7 @@ protected void initializeFromXML( Element el ) { super.initializeFromXML( el ); m_alias = el.getChildText( "alias" ); + m_ajaxAlias = el.getChildText( "ajaxAlias" ); } /** @@ -674,6 +682,14 @@ public String getAlias() { return m_alias; } + + /** + * Returns the ajax alias name for this object. + * @return An ajax alias name for the plugin. + */ + public String getAjaxAlias() { + return m_ajaxAlias; + } /** * Creates a new plugin instance. Index: jspwiki-war/src/main/java/org/apache/wiki/plugin/SampleAjaxPlugin.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/plugin/SampleAjaxPlugin.java (revision 1655294) +++ jspwiki-war/src/main/java/org/apache/wiki/plugin/SampleAjaxPlugin.java (working copy) @@ -19,48 +19,46 @@ package org.apache.wiki.plugin; import java.io.IOException; +import java.util.List; import java.util.Map; import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.wiki.WikiContext; +import org.apache.wiki.ajax.WikiAjaxServlet; import org.apache.wiki.api.exceptions.PluginException; import org.apache.wiki.api.plugin.WikiPlugin; /** - * @author David VIttor - * @date 20/01/2015 * @since 2.10.2-svn10 */ -public class SampleAjaxPlugin extends HttpServlet implements WikiPlugin { - private static final long serialVersionUID = 1L; +public class SampleAjaxPlugin implements WikiPlugin, WikiAjaxServlet { + + private static final String SERVLET_MAPPING = "SampleAjaxPlugin"; @Override public String execute(WikiContext context, Map params) throws PluginException { String id = Integer.toString(this.hashCode()); - String baseUrl = context.getEngine().getBaseURL(); - String url = baseUrl+"ajax/SampleAjaxPlugin"; - String html= "

Press Me
\n"+ + String html= "
Press Me
\n"+ "
"; return html; } - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + @Override + public String getServletMapping() { + return SERVLET_MAPPING; + } + + @Override + public void service(HttpServletRequest request, HttpServletResponse response, String actionName, List params) throws ServletException, IOException { try { Thread.sleep(5000); // Wait 5 seconds } catch (Exception e) {} - resp.getWriter().print("You called by get!"); - } + response.getWriter().print("You called!"); + } - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - try { - Thread.sleep(5000); // Wait 5 seconds - } catch (Exception e) {} - resp.getWriter().print("You called by post!"); - } + + } Index: jspwiki-war/src/main/java/org/apache/wiki/Release.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/Release.java (revision 1655294) +++ jspwiki-war/src/main/java/org/apache/wiki/Release.java (working copy) @@ -72,7 +72,7 @@ *

* If the build identifier is empty, it is not added. */ - public static final String BUILD = "11"; + public static final String BUILD = "12"; /** * This is the generic version string you should use when printing out the version. It is of Index: jspwiki-war/src/main/java/org/apache/wiki/rpc/json/JSONRPCManager.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/rpc/json/JSONRPCManager.java (revision 1655294) +++ jspwiki-war/src/main/java/org/apache/wiki/rpc/json/JSONRPCManager.java (working copy) @@ -27,15 +27,15 @@ import javax.servlet.http.HttpSession; import org.apache.log4j.Logger; - import org.apache.wiki.WikiContext; import org.apache.wiki.WikiEngine; import org.apache.wiki.WikiSession; +import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; import org.apache.wiki.auth.WikiSecurityException; import org.apache.wiki.auth.permissions.PagePermission; import org.apache.wiki.rpc.RPCCallable; import org.apache.wiki.rpc.RPCManager; -import org.apache.wiki.ui.TemplateManager; + import com.metaparadigm.jsonrpc.InvocationCallback; import com.metaparadigm.jsonrpc.JSONRPCBridge; @@ -51,10 +51,13 @@ * Due to some limitations of the JSON-RPC library, we do not use the * Global bridge object. * + * Deprecated: Use {@link WikiAjaxDispatcherServlet} + * * @see org.apache.wiki.rpc.RPCCallable * @since 2.5.4 */ // FIXME: Must be mootool-ified. +@Deprecated public final class JSONRPCManager extends RPCManager { private static final String JSONRPCBRIDGE = "JSONRPCBridge"; private static HashMap c_globalObjects = new HashMap(); Index: jspwiki-war/src/main/java/org/apache/wiki/rpc/RPCCallable.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/rpc/RPCCallable.java (revision 1655294) +++ jspwiki-war/src/main/java/org/apache/wiki/rpc/RPCCallable.java (working copy) @@ -18,11 +18,16 @@ */ package org.apache.wiki.rpc; +import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; + /** * Defines an interface for anything which can be called using the RPC methods. * + * Deprecated. Use {@link WikiAjaxDispatcherServlet} + * * @since 2.5.4 */ +@Deprecated public interface RPCCallable { Index: jspwiki-war/src/main/java/org/apache/wiki/rpc/RPCManager.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/rpc/RPCManager.java (revision 1655294) +++ jspwiki-war/src/main/java/org/apache/wiki/rpc/RPCManager.java (working copy) @@ -18,11 +18,16 @@ */ package org.apache.wiki.rpc; +import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; + /** * A base class for managing RPC calls. * * @since 2.5.4 + * + * Deprecated. Use {@link WikiAjaxDispatcherServlet} */ +@Deprecated public class RPCManager { /** Index: jspwiki-war/src/main/java/org/apache/wiki/search/SearchManager.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/search/SearchManager.java (revision 1655294) +++ jspwiki-war/src/main/java/org/apache/wiki/search/SearchManager.java (working copy) @@ -24,14 +24,23 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.Set; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.StopWatch; import org.apache.log4j.Logger; import org.apache.wiki.WikiContext; import org.apache.wiki.WikiEngine; import org.apache.wiki.WikiPage; +import org.apache.wiki.ajax.AjaxUtil; +import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; +import org.apache.wiki.ajax.WikiAjaxServlet; import org.apache.wiki.api.exceptions.FilterException; import org.apache.wiki.api.exceptions.NoRequiredPropertyException; import org.apache.wiki.api.exceptions.ProviderException; @@ -42,12 +51,9 @@ import org.apache.wiki.event.WikiPageEvent; import org.apache.wiki.modules.InternalModule; import org.apache.wiki.parser.MarkupParser; -import org.apache.wiki.rpc.RPCCallable; -import org.apache.wiki.rpc.json.JSONRPCManager; import org.apache.wiki.util.ClassUtil; import org.apache.wiki.util.TextUtil; - /** * Manages searching the Wiki. * @@ -89,14 +95,61 @@ WikiEventUtils.addWikiEventListener(m_engine.getPageManager(), WikiPageEvent.PAGE_DELETE_REQUEST, this); - JSONRPCManager.registerGlobalObject( JSON_SEARCH, new JSONSearch() ); + //TODO: Replace with custom annotations. See JSPWIKI-566 + WikiAjaxDispatcherServlet.registerServlet( JSON_SEARCH, new JSONSearch() ); } /** * Provides a JSON RPC API to the JSPWiki Search Engine. */ - public class JSONSearch implements RPCCallable + public class JSONSearch implements WikiAjaxServlet { + public static final String AJAX_ACTION_SUGGESTIONS = "suggestions"; + public static final String AJAX_ACTION_PAGES = "pages"; + public static final int DEFAULT_MAX_RESULTS = 20; + public int maxResults = DEFAULT_MAX_RESULTS; + + @Override + public String getServletMapping() { + return JSON_SEARCH; + } + + @Override + public void service(HttpServletRequest req, HttpServletResponse resp, String actionName, List params) + throws ServletException, IOException { + String result = ""; + if (StringUtils.isNotBlank(actionName)) { + if (params.size()<1) { + return; + } + String itemId = params.get(1); + log.debug("itemId="+itemId); + if (params.size()>1) { + String maxResultsParam = params.get(2); + log.debug("maxResultsParam="+maxResultsParam); + if (StringUtils.isNotBlank(maxResultsParam) && StringUtils.isNumeric(maxResultsParam)) { + maxResults = Integer.parseInt(maxResultsParam); + } + } + + if (actionName.equals(AJAX_ACTION_SUGGESTIONS)) { + List callResults = new ArrayList(); + log.debug("Calling getSuggestions() START"); + callResults = getSuggestions(itemId, maxResults); + log.debug("Calling getSuggestions() DONE. "+callResults.size()); + result = AjaxUtil.toJson(callResults); + } else if (actionName.equals(AJAX_ACTION_PAGES)) { + List> callResults = new ArrayList>(); + log.debug("Calling findPages() START"); + callResults = findPages(itemId, maxResults); + log.debug("Calling findPages() DONE. "+callResults.size()); + result = AjaxUtil.toJson(callResults); + } + } + log.debug("result="+result); + resp.getWriter().write(result); + } + /** * Provides a list of suggestions to use for a page name. * Currently the algorithm just looks into the value parameter, @@ -106,7 +159,7 @@ * @param maxLength maximum number of suggestions * @return the suggestions */ - public List getSuggestions( String wikiName, int maxLength ) + public List getSuggestions( String wikiName, int maxLength ) { StopWatch sw = new StopWatch(); sw.start(); @@ -155,12 +208,12 @@ * @param maxLength How many hits to return * @return the pages found */ - public List findPages( String searchString, int maxLength ) + public List> findPages( String searchString, int maxLength ) { StopWatch sw = new StopWatch(); sw.start(); - List list = new ArrayList(maxLength); + List> list = new ArrayList>(maxLength); if( searchString.length() > 0 ) { @@ -168,11 +221,12 @@ { Collection c; - if( m_searchProvider instanceof LuceneSearchProvider ) + if( m_searchProvider instanceof LuceneSearchProvider ) { c = ((LuceneSearchProvider)m_searchProvider).findPages( searchString, 0 ); - else + } else { c = m_searchProvider.findPages( searchString ); - + } + int count = 0; for( Iterator i = c.iterator(); i.hasNext() && count < maxLength; count++ ) { @@ -195,6 +249,7 @@ } } + /** * This particular method starts off indexing and all sorts of various activities, * so you need to run this last, after things are done. Index: jspwiki-war/src/main/java/org/apache/wiki/tags/AdminBeanIteratorTag.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/tags/AdminBeanIteratorTag.java (revision 1655294) +++ jspwiki-war/src/main/java/org/apache/wiki/tags/AdminBeanIteratorTag.java (working copy) @@ -22,6 +22,7 @@ import java.util.Collection; import java.util.Iterator; +import org.apache.wiki.WikiContext; import org.apache.wiki.api.engine.AdminBeanManager; import org.apache.wiki.ui.admin.AdminBean; @@ -41,6 +42,9 @@ * @param type Type to set */ public void setType( String type ) { + if (m_wikiContext == null) { + m_wikiContext = WikiContext.findContext(pageContext); + } m_type = m_wikiContext.getEngine().getAdminBeanManager().getTypeFromString( type ); } Index: jspwiki-war/src/main/java/org/apache/wiki/ui/progress/ProgressManager.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/ui/progress/ProgressManager.java (revision 1655294) +++ jspwiki-war/src/main/java/org/apache/wiki/ui/progress/ProgressManager.java (working copy) @@ -18,15 +18,20 @@ */ package org.apache.wiki.ui.progress; +import java.io.IOException; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import org.apache.log4j.Logger; +import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; +import org.apache.wiki.ajax.WikiAjaxServlet; -import org.apache.wiki.rpc.RPCCallable; -import org.apache.wiki.rpc.json.JSONRPCManager; - /** * Manages progressing items. In general this class is used whenever JSPWiki * is doing something which may require a long time. In addition, this manager @@ -52,7 +57,8 @@ */ public ProgressManager() { - JSONRPCManager.registerGlobalObject( JSON_PROGRESSTRACKER, new JSONTracker() ); + //TODO: Replace with custom annotations. See JSPWIKI-566 + WikiAjaxDispatcherServlet.registerServlet( JSON_PROGRESSTRACKER, new JSONTracker() ); } /** @@ -117,7 +123,7 @@ * Progress of zero (0) means that the progress has just started, and a progress of * 100 means that it is complete. */ - public class JSONTracker implements RPCCallable + public class JSONTracker implements WikiAjaxServlet { /** * Returns upload progress in percents so far. @@ -129,5 +135,31 @@ { return ProgressManager.this.getProgress( progressId ); } + + public String getServletMapping() { + return JSON_PROGRESSTRACKER; + } + + public void service(HttpServletRequest req, HttpServletResponse resp, String actionName, List params) + throws ServletException, IOException + { + log.debug("ProgressManager.doGet() START"); + if (params.size()<1) { + return; + } + String progressId = params.get(1); + log.debug("progressId="+progressId); + String progressString = ""; + try { + int progress = getProgress(progressId); + progressString = Integer.toString(progress); + } catch (IllegalArgumentException e) { + // ignore + log.debug("progressId "+progressId+" is no longer valid"); + } + log.debug("progressString="+progressString); + resp.getWriter().write(progressString); + log.debug("ProgressManager.doGet() DONE"); + } } } Index: jspwiki-war/src/main/java/org/apache/wiki/WikiAjaxDispatcherServlet.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/WikiAjaxDispatcherServlet.java (revision 1655294) +++ jspwiki-war/src/main/java/org/apache/wiki/WikiAjaxDispatcherServlet.java (working copy) @@ -1,146 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache 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.apache.org/licenses/LICENSE-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.apache.wiki; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang.StringUtils; -import org.apache.log4j.Logger; - -/** - * This provides a simple ajax servlet for handling /ajax/ requests. - * Classes need to be registered using {@link WikiAjaxDispatcherServlet.register} - * - * @author David VIttor - * @date 20/01/2015 - * @since 2.10.2-svn10 - */ -public class WikiAjaxDispatcherServlet extends HttpServlet { - private static final long serialVersionUID = 1L; - private static Map ajaxServlets = new HashMap(); - static final Logger log = Logger.getLogger(WikiAjaxDispatcherServlet.class.getName()); - private static final String PATH_AJAX = "/ajax/"; - - /** - * {@inheritDoc} - */ - public void init(ServletConfig config) - throws ServletException { - super.init(config); - - log.info("WikiAjaxDispatcherServlet initialized."); - } - - public static void register(HttpServlet servlet) { - log.info("WikiAjaxDispatcherServlet registering "+servlet.getClass().getSimpleName()+"="+servlet); - ajaxServlets.put(servlet.getClass().getSimpleName(),servlet); - } - - /** - * Calls {@link this.performAction} - */ - public void doPost(HttpServletRequest req, HttpServletResponse res) - throws IOException, ServletException { - performAction(req,res); - } - - /** - * Calls {@link this.performAction} - */ - public void doGet(HttpServletRequest req, HttpServletResponse res) - throws IOException, ServletException { - performAction(req,res); - } - - /** - * The main method which get the requestURI "/ajax/", gets the - * {@link this.getServletName} and finds the servlet using {@link this.findServletByName}. - * It then calls servlet.service(). - * @param req the inbound request - * @param res the outbound response - * @throws IOException - * @throws ServletException if no registered servlet can be found - */ - private void performAction(HttpServletRequest req, HttpServletResponse res) - throws IOException, ServletException { - String path = req.getRequestURI(); - String servletName = getServletName(path); - if (servletName!=null) { - HttpServlet ajaxServlet = findServletByName(servletName); - if (ajaxServlet != null) { - ajaxServlet.service(req, res); - } else { - log.error("No registered class for servletName=" + servletName + " in path=" + path); - throw new ServletException("No registered class for servletName=" + servletName); - } - } - } - - /** - * Get the name of the servlet given the requestURI. - * @param path The requestURI, which must contains "/ajax/" in the path - * @return The ServletName for the requestURI, or null - * @throws ServletException if the path is invalid - */ - public String getServletName(String path) throws ServletException { - String result = null; - if (StringUtils.isBlank(path)) { - return result; - } - int index = path.indexOf(PATH_AJAX); - if (index<0) { - throw new ServletException("Invalid path provided " + path + " does not contain '" + PATH_AJAX + "'"); - } - path = path.substring(index+6); - index = path.indexOf("/"); - if (index == -1) { - index = path.indexOf("#"); - if (index == -1) { - index = path.indexOf("?"); - } - } - if (index == -1) { - result = path; - } - else { - result = path.substring(0,index); - } - - return result; - } - - /** - * Find the servlet as registered in {@link WikiAjaxDispatcherServlet.register}. - * - * @param servletName the name of the servlet from {@link this.getServletNamee} - * @return The first servlet found, or null. - */ - public HttpServlet findServletByName(String servletName) { - return ajaxServlets.get(servletName); - } - -} Index: jspwiki-war/src/main/java/org/apache/wiki/xmlrpc/RPCServlet.java =================================================================== --- jspwiki-war/src/main/java/org/apache/wiki/xmlrpc/RPCServlet.java (revision 1655294) +++ jspwiki-war/src/main/java/org/apache/wiki/xmlrpc/RPCServlet.java (working copy) @@ -32,9 +32,9 @@ import org.apache.log4j.Logger; import org.apache.xmlrpc.*; - import org.apache.wiki.WikiContext; import org.apache.wiki.WikiEngine; +import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; /** * Handles all incoming servlet requests for XML-RPC calls. Index: jspwiki-war/src/main/scripts/jspwiki-common.js =================================================================== --- jspwiki-war/src/main/scripts/jspwiki-common.js (revision 1655294) +++ jspwiki-war/src/main/scripts/jspwiki-common.js (working copy) @@ -219,67 +219,6 @@ } } -/** AJAX Requests as per http://javapapers.com/ajax/getting-started-with-ajax-using-java/ **/ -/* - * creates a new XMLHttpRequest object which is the backbone of AJAX, - * or returns false if the browser doesn't support it - */ -function getXMLHttpRequest() { - var xmlHttpReq = false; - // to create XMLHttpRequest object in non-Microsoft browsers - if (window.XMLHttpRequest) { - xmlHttpReq = new XMLHttpRequest(); - } else if (window.ActiveXObject) { - try { - // to create XMLHttpRequest object in later versions - // of Internet Explorer - xmlHttpReq = new ActiveXObject("Msxml2.XMLHTTP"); - } catch (exp1) { - try { - // to create XMLHttpRequest object in older versions - // of Internet Explorer - xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP"); - } catch (exp2) { - xmlHttpReq = false; - } - } - } - return xmlHttpReq; -} - -/* - * AJAX call starts with this function - */ -function makeRequest(method,url,responseId,loading) { - var xmlHttpRequest = getXMLHttpRequest(); - xmlHttpRequest.onreadystatechange = getReadyStateHandler(xmlHttpRequest,responseId,loading); - xmlHttpRequest.open(method, url, true); - xmlHttpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - xmlHttpRequest.send(null); -} - -/* - * Returns a function that waits for the state change in XMLHttpRequest - */ -function getReadyStateHandler(xmlHttpRequest,responseId,loading) { - // an anonymous function returned - // it listens to the XMLHttpRequest instance - return function() { - if (xmlHttpRequest.readyState >=1 && xmlHttpRequest.readyState <4) { - document.getElementById(responseId).innerHTML = loading; - } - if (xmlHttpRequest.readyState == 4) { - if (xmlHttpRequest.status == 200) { - document.getElementById(responseId).innerHTML = xmlHttpRequest.responseText; - } else { - document.getElementById(responseId).innerHTML("HTTP error " + xmlHttpRequest.status + ": " + xmlHttpRequest.statusText); - } - } - }; -} -/** End AJAX Requests **/ - - /** 100 Wiki functions **/ var Wiki = { @@ -439,11 +378,11 @@ submitUpload: function(form, progress){ $('progressbar').setStyle('visibility','visible'); this.progressbar = - Wiki.jsonrpc.periodical(1000, this, ["progressTracker.getProgress",[progress],function(result){ - result = result.stripScripts(); //xss vulnerability - if(!result.code) $('progressbar').getFirst().setStyle('width',result+'%').setHTML(result+'%'); + Wiki.ajaxJsonCall.periodical(500, this, ["/progressTracker",[progress],function(result){ + if(result) { + $('progressbar').getFirst().setStyle('width',result+'%').setHTML(result+'%'); + } }]); - return Wiki.submitOnce(form); }, @@ -472,26 +411,42 @@ ); }, - $jsonid : 10000, - jsonrpc: function(method, params, fn) { - $$('meta').each(function(el){ - var n = el.getProperty('name') || ''; - if( n.indexOf('wiki') == 0 ) this[n.substr(4)] = el.getProperty('content'); - },this); + /* + * AJAX call starts with these functions which rely on the Mootools Request.HTML and Request.JSON + * http://mootools.net/core/docs/1.5.1/Request/Request.JSON + */ + ajaxHtmlCall:function(url, params, responseId, loading){ + var update = document.getElementById(responseId); + if (update){ update.innerHTML = loading||'Loading...'; } - if (Wiki.JsonUrl) { - new Ajax( Wiki.JsonUrl, { - postBody: Json.toString({"id":Wiki.$jsonid++, "method":method, "params":params}), - method: 'post', - onComplete: function(result){ - var r = Json.evaluate(result,true); - if(r){ - if(r.result){ fn(r.result) } - else if(r.error){ fn(r.error) } - } + new Request.HTML({ + url: this.JsonUrl + url, + method:'post', // defaults to 'POST' + update: update + }).send({ + params: params + }); + }, + ajaxJsonCall: function(url, params, callback){ + //the Request.JSON does all encoding and decoding of the JSON automatically + new Request.JSON({ + url: this.JsonURL + url, + method:'post', + onSuccess: function(response){ + if(response.error){ + console.log(response.error); + callback(null); + } else { + callback(response.result) + } + }, + onError: function(response){ + console.log(response.error); + callback(null); } - }).request(); - } + }).send({ + params: params + }); } } @@ -1005,20 +960,20 @@ $('searchTarget').setHTML('('+qv+') :'); $('searchSpin').show(); - Wiki.jsonrpc('search.findPages', [qv,20], function(result){ - $('searchSpin').hide(); - if(!result.list) return; - var frag = new Element('ul'); + Wiki.ajaxJsonCall("/search/pages",[qv,'20'], function(result) { + $('searchSpin').hide(); + if(!result) return; + var frag = new Element('ul'); - result.list.each(function(el){ - new Element('li').adopt( - new Element('a',{'href':Wiki.getUrl(el.map.page) }).setHTML(el.map.page), - new Element('span',{'class':'small'}).setHTML(" ("+el.map.score+")") - ).inject(frag); - }); - $('searchOutput').empty().adopt(frag); - Wiki.locatemenu( $('query'), $('searchboxMenu') ); - }); + result.each(function(el){ + new Element('li').adopt( + new Element('a',{'href':Wiki.getUrl(el.page) }).setHTML(el.page), + new Element('span',{'class':'small'}).setHTML(" ("+el.score+")") + ).inject(frag); + }); + $('searchOutput').empty().adopt(frag); + Wiki.locatemenu( $('query'), $('searchboxMenu') ); + }); } , /* navigate to url, after smart pagename handling */ Index: jspwiki-war/src/main/scripts/jspwiki-edit.js =================================================================== --- jspwiki-war/src/main/scripts/jspwiki-edit.js (revision 1655294) +++ jspwiki-war/src/main/scripts/jspwiki-edit.js (working copy) @@ -456,14 +456,12 @@ if(end!=-1) sel.end = sel.start+end; } - Wiki.jsonrpc('search.getSuggestions', [searchword,30], function(result,exception){ - if(exception) { - alert(exception.message); - } else if(!result.list || (result.list.length == 0)) { + Wiki.ajaxJsonCall('/search/suggestions',[searchword,'30'], function(result){ + if(!result) { suggest.hide(); } else { var ul = new Element('ul').inject( suggest.empty().show() ); - result.list.each( function(rslt) { + result.each( function(rslt) { new Element('li',{ 'title':rslt, 'events': { Index: jspwiki-war/src/main/scripts/wiki-edit/Wiki.Snips.js =================================================================== --- jspwiki-war/src/main/scripts/wiki-edit/Wiki.Snips.js (revision 1655294) +++ jspwiki-war/src/main/scripts/wiki-edit/Wiki.Snips.js (working copy) @@ -371,17 +371,14 @@ if( !key || (key.trim()=='')) key = Wiki.PageName + '/'; //console.log('json lookup for '+key); - Wiki.jsonrpc('search.getSuggestions', [key,30], function(result,exception){ - - if( result.list && result.list[0] /*length!=0*/ ){ - dialog.setBody( result.list ); - } else { - dialog.hide(); - } - - }); + Wiki.ajaxJsonCall("/search/suggestions",[key,30], function(result) { + if( result && result.size()>0 ){ + dialog.setBody( result ); + } else { + dialog.hide(); + } + }); } - }] Index: jspwiki-war/src/main/scripts/wiki/Findpages.js =================================================================== --- jspwiki-war/src/main/scripts/wiki/Findpages.js (revision 1655294) +++ jspwiki-war/src/main/scripts/wiki/Findpages.js (working copy) @@ -27,7 +27,7 @@ Example: > wiki.add('query', Wiki.SearchBox, { -> rpc: function(value, callback){ wiki.jsonrpc('search.findPages', [value,20], callback }, +> rpc: function(value, callback){ Wiki.ajaxJsonCall('/search/findPages',[value,'20'], callback }, > toUrl: wiki.toUrl > }); */ Index: jspwiki-war/src/main/scripts/wiki/Wiki.js =================================================================== --- jspwiki-war/src/main/scripts/wiki/Wiki.js (revision 1655294) +++ jspwiki-war/src/main/scripts/wiki/Wiki.js (working copy) @@ -166,7 +166,7 @@ //activate Quick Navigation functionality new wiki.Findpages(element,{ rpc: function(value, callback){ - wiki.jsonrpc('search.findPages', [value,16], callback); + Wiki.ajaxJsonCall('/search/pages',[value,'16'], callback); }, toUrl: wiki.toUrl.bind(wiki) }); @@ -189,7 +189,7 @@ .add('#files', Form.File, { max:1, //CHECK: jspwiki v.2.10.x seems to only support 1 upload-file at a time ?? rpc: function(progressid, callback){ - wiki.jsonrpc('progressTracker.getProgress', [progressid], callback); + Wiki.ajaxJsonCall('/progressTracker',[progressId], callback); }, }); @@ -423,18 +423,18 @@ {{{ }}} Supported rpc calls: - - {{search.findPages}} gets the list of pagenames with partial match - - {{progressTracker.getProgress}} get a progress indicator of attachment upload - - {{search.getSuggestions}} gets the list of pagenames with partial match + - {{ajax/users/}} gets the details of the current user id + - {{ajax/search/pages/}} gets the list of pagenames with partial match + - {{ajax/search/suggestions/}} gets the list of pagenames with partial match + - {{ajax/progressTracker/}} get a progress indicator of attachment upload Example: (start code) - Wiki.jsonrpc('search.findPages', ['Janne',20], function(result){ + Wiki.ajaxJsonCall('/search/pages,[Janne,20]', function(result){ //do something with the resulting json object }); (end) - - */ + jsonid : 1e4, //seed jsonrpc: function(method, params, callback){ @@ -461,6 +461,7 @@ } } + */ }; Index: jspwiki-war/src/main/webapp/templates/default/admin/UserManagement.jsp =================================================================== --- jspwiki-war/src/main/webapp/templates/default/admin/UserManagement.jsp (revision 1655294) +++ jspwiki-war/src/main/webapp/templates/default/admin/UserManagement.jsp (working copy) @@ -41,13 +41,13 @@ if( userid == '--New--' ) return; - Wiki.jsonrpc("users.getUserInfo", [userid], function(userprofile){ - $('loginname').value = userprofile.loginName; - $('loginid').value = userprofile.loginName; - $('fullname').value = userprofile.fullname; - $('email').value = userprofile.email; - $('lastmodified').setHTML(constructdate(userprofile.lastModified)); - $('creationdate').setHTML(constructdate(userprofile.created)); + Wiki.ajaxJsonCall("/users/"+userid, function(userprofile) { + $('loginname').value = userprofile.loginName; + $('loginid').value = userprofile.loginName; + $('fullname').value = userprofile.fullname; + $('email').value = userprofile.email; + $('lastmodified').setHTML(constructdate(userprofile.lastModified)); + $('creationdate').setHTML(constructdate(userprofile.created)); }); } Index: jspwiki-war/src/main/webapp/templates/default/commonheader.jsp =================================================================== --- jspwiki-war/src/main/webapp/templates/default/commonheader.jsp (revision 1655294) +++ jspwiki-war/src/main/webapp/templates/default/commonheader.jsp (working copy) @@ -67,7 +67,7 @@ -<%--unusual pagename--%> +<%--unusual pagename--%> <%--pagename without blanks--%> Index: jspwiki-war/src/main/webapp/templates/haddock/admin/UserManagement.jsp =================================================================== --- jspwiki-war/src/main/webapp/templates/haddock/admin/UserManagement.jsp (revision 1655294) +++ jspwiki-war/src/main/webapp/templates/haddock/admin/UserManagement.jsp (working copy) @@ -41,13 +41,13 @@ if( userid == '--New--' ) return; - Wiki.jsonrpc("users.getUserInfo", [userid], function(userprofile){ - $('loginname').value = userprofile.loginName; - $('loginid').value = userprofile.loginName; - $('fullname').value = userprofile.fullname; - $('email').value = userprofile.email; - $('lastmodified').setHTML(constructdate(userprofile.lastModified)); - $('creationdate').setHTML(constructdate(userprofile.created)); + Wiki.ajaxJsonCall("/users",[userid], function(userprofile) { + $('loginname').value = userprofile.loginName; + $('loginid').value = userprofile.loginName; + $('fullname').value = userprofile.fullname; + $('email').value = userprofile.email; + $('lastmodified').setHTML(constructdate(userprofile.lastModified)); + $('creationdate').setHTML(constructdate(userprofile.created)); }); } Index: jspwiki-war/src/main/webapp/templates/haddock/commonheader.jsp =================================================================== --- jspwiki-war/src/main/webapp/templates/haddock/commonheader.jsp (revision 1655294) +++ jspwiki-war/src/main/webapp/templates/haddock/commonheader.jsp (working copy) @@ -81,7 +81,7 @@ -<%--unusual pagename--%> +<%--unusual pagename--%> <%--pagename without blanks--%> Index: jspwiki-war/src/main/webapp/WEB-INF/web.xml =================================================================== --- jspwiki-war/src/main/webapp/WEB-INF/web.xml (revision 1655294) +++ jspwiki-war/src/main/webapp/WEB-INF/web.xml (working copy) @@ -127,6 +127,13 @@ com.metaparadigm.jsonrpc.JSONRPCServlet com.metaparadigm.jsonrpc.JSONRPCServlet + + + + WikiAjaxDispatcherServlet + org.apache.wiki.ajax.WikiAjaxDispatcherServlet + 1 + @@ -141,13 +148,6 @@ 1 - - - WikiAjaxDispatcherServlet - org.apache.wiki.WikiAjaxDispatcherServlet - 1 - - @@ -170,6 +170,7 @@ WikiAjaxDispatcherServlet /ajax/* + /admin/ajax/* Index: jspwiki-war/src/test/java/org/apache/wiki/WikiAjaxServletTest.java =================================================================== --- jspwiki-war/src/test/java/org/apache/wiki/WikiAjaxServletTest.java (revision 1655294) +++ jspwiki-war/src/test/java/org/apache/wiki/WikiAjaxServletTest.java (working copy) @@ -18,16 +18,13 @@ */ package org.apache.wiki; -import javax.servlet.http.HttpServlet; - import junit.framework.TestCase; +import org.apache.wiki.ajax.WikiAjaxDispatcherServlet; +import org.apache.wiki.ajax.WikiAjaxServlet; import org.apache.wiki.plugin.SampleAjaxPlugin; -import org.apache.wiki.xmlrpc.RPCServlet; /** - * @author David VIttor - * @date 20/01/2015 * @since 2.10.2-svn10 */ public class WikiAjaxServletTest extends TestCase { @@ -52,17 +49,19 @@ } // The plugin SampleAjaxPlugin - WikiAjaxDispatcherServlet.register(new SampleAjaxPlugin()); - HttpServlet servlet = wikiAjaxDispatcherServlet.findServletByName("SampleAjaxPlugin"); + WikiAjaxDispatcherServlet.registerServlet(new SampleAjaxPlugin()); + WikiAjaxServlet servlet = wikiAjaxDispatcherServlet.findServletByName("SampleAjaxPlugin"); assertNotNull(servlet); assertTrue(servlet instanceof SampleAjaxPlugin); - WikiAjaxDispatcherServlet.register(new RPCServlet()); - HttpServlet servlet2 = wikiAjaxDispatcherServlet.findServletByName("RPCServlet"); + /** Note sure about this + WikiAjaxDispatcherServlet.registerServlet(new RPCServlet()); + WikiAjaxServlet servlet2 = wikiAjaxDispatcherServlet.findServletByName("RPCServlet"); assertNotNull(servlet2); assertTrue(servlet2 instanceof RPCServlet); + */ - HttpServlet servlet3 = wikiAjaxDispatcherServlet.findServletByName("TestWikiNonAjaxServlet"); + WikiAjaxServlet servlet3 = wikiAjaxDispatcherServlet.findServletByName("TestWikiNonAjaxServlet"); assertNull(servlet3); } Index: jspwiki-war/src/test/resources/WEB-INF/web.xml =================================================================== --- jspwiki-war/src/test/resources/WEB-INF/web.xml (revision 1655294) +++ jspwiki-war/src/test/resources/WEB-INF/web.xml (working copy) @@ -148,6 +148,13 @@ com.metaparadigm.jsonrpc.JSONRPCServlet com.metaparadigm.jsonrpc.JSONRPCServlet + + + + WikiAjaxDispatcherServlet + org.apache.wiki.ajax.WikiAjaxDispatcherServlet + 1 + @@ -211,6 +218,12 @@ + WikiAjaxDispatcherServlet + /ajax/* + /admin/ajax/* + + + com.metaparadigm.jsonrpc.JSONRPCServlet /JSON-RPC Index: pom.xml =================================================================== --- pom.xml (revision 1655294) +++ pom.xml (working copy) @@ -73,6 +73,12 @@ + com.google.code.gson + gson + 2.3.1 + + + commons-fileupload commons-fileupload 1.3