1 23 24 package org.apache.slide.webdav; 25 26 import java.io.IOException ; 27 import java.text.SimpleDateFormat ; 28 import java.util.Date ; 29 30 import javax.servlet.RequestDispatcher ; 31 import javax.servlet.ServletConfig ; 32 import javax.servlet.ServletException ; 33 import javax.servlet.http.HttpServlet ; 34 import javax.servlet.http.HttpServletRequest ; 35 import javax.servlet.http.HttpServletResponse ; 36 import javax.xml.parsers.DocumentBuilderFactory ; 37 import javax.xml.parsers.ParserConfigurationException ; 38 import javax.xml.parsers.FactoryConfigurationError ; 39 40 import org.apache.slide.authenticate.SecurityToken; 41 import org.apache.slide.common.Domain; 42 import org.apache.slide.common.NamespaceAccessToken; 43 import org.apache.slide.common.SlideException; 44 import org.apache.slide.common.SlideToken; 45 import org.apache.slide.common.SlideTokenWrapper; 46 import org.apache.slide.security.AccessDeniedException; 47 import org.apache.slide.structure.LinkedObjectNotFoundException; 48 import org.apache.slide.structure.ObjectNotFoundException; 49 import org.apache.slide.util.logger.Logger; 50 import org.apache.slide.util.Configuration; 51 import org.apache.slide.webdav.util.DirectoryIndexGenerator; 52 import org.apache.slide.webdav.util.WebdavUtils; 53 import org.apache.slide.webdav.method.*; 54 import org.apache.webdav.lib.util.WebdavStatus; 55 import org.jahia.bin.Jahia; 56 import org.jahia.services.webdav.HttpRequestWrapper; 57 import org.jahia.services.database.ConnectionDispenser; 58 import org.jahia.services.cache.CacheFactory; 59 import org.jahia.exceptions.JahiaException; 60 61 70 public class JahiaWebdavServlet 71 extends HttpServlet { 72 73 74 76 77 80 private static final String LOG_CHANNEL = JahiaWebdavServlet.class.getName(); 81 82 83 85 public static final String ATTRIBUTE_NAME = 86 "org.apache.slide.NamespaceAccessToken"; 87 88 91 protected boolean directoryBrowsing = true; 92 93 96 private boolean authenticate; 97 98 101 protected RequestDispatcher directoryBrowsingTemplate; 102 103 105 protected void service (HttpServletRequest req, HttpServletResponse resp) 106 throws ServletException , IOException { 107 108 req.setAttribute("slide_uri", WebdavUtils.getRelativePath(req, (WebdavServletConfig) getServletConfig())); 109 110 try { 111 req = new HttpRequestWrapper(req); 112 } catch (JahiaException e) { 113 e.printStackTrace(); 114 resp.sendError(WebdavStatus.SC_INTERNAL_SERVER_ERROR); 115 } 116 NamespaceAccessToken token = (NamespaceAccessToken) req.getAttribute(HttpRequestWrapper.TOKEN_ATTRIBUTE); 117 118 if (token == null) { 119 resp.sendError(HttpServletResponse.SC_NOT_FOUND); 120 return; 121 } 122 123 SimpleDateFormat sdf = new SimpleDateFormat (); 124 if( token.getLogger().isEnabled(LOG_CHANNEL, Logger.DEBUG) ) 125 token.getLogger().log("==> "+req.getMethod()+" start: "+sdf.format(new Date (System.currentTimeMillis()))+" ["+Thread.currentThread().getName()+"]", LOG_CHANNEL, Logger.DEBUG); 126 127 if (authenticate && 128 !req.getMethod().equals("GET") && 129 !req.getMethod().equals("HEAD") && 130 req.getUserPrincipal() == null) { 131 resp.addHeader("WWW-Authenticate", "BASIC realm=\"" + token.getName() + "\""); 132 resp.sendError(HttpServletResponse.SC_UNAUTHORIZED); 133 } 134 135 try { 136 137 if (token == null) { 138 String namespaceName = req.getContextPath(); 139 if ((namespaceName == null) || (namespaceName.equals(""))) { 140 namespaceName = Domain.getDefaultNamespace(); 141 } 142 while (namespaceName.startsWith("/")) { 143 namespaceName = namespaceName.substring(1); 144 } 145 token = Domain.accessNamespace(new SecurityToken(this), namespaceName); 146 } 147 148 req.setAttribute(ATTRIBUTE_NAME, token); 149 150 resp.setStatus(WebdavStatus.SC_OK); 151 152 String methodName = req.getMethod(); 153 if ((methodName.equalsIgnoreCase("GET") || 154 methodName.equalsIgnoreCase("POST")) && 155 isCollection(token, req)) { 156 super.service(req, resp); 160 } else { 161 WebdavMethod method = createMethod(token, methodName); 162 if (method == null) { 163 throw new WebdavException(WebdavStatus.SC_METHOD_NOT_ALLOWED); 164 } else { 165 method.run(req, resp); 166 } 167 } 168 } catch (WebdavException e) { 169 token.getLogger().log(e,LOG_CHANNEL, Logger.ERROR); 171 try { resp.sendError(e.getStatusCode()); } catch (Throwable ex) { } 172 if (e.getStatusCode() == WebdavStatus.SC_UNAUTHORIZED) { 173 resp.addHeader("WWW-Authenticate", "BASIC realm=\"" + ((NamespaceAccessToken) req.getAttribute(HttpRequestWrapper.TOKEN_ATTRIBUTE)).getName() + "\""); 174 } 175 } catch (Throwable e) { 176 token.getLogger().log(e,LOG_CHANNEL, Logger.ERROR); 178 try { resp.sendError(WebdavStatus.SC_INTERNAL_SERVER_ERROR); } catch (Throwable ex) { } 179 } 180 finally { 181 if( token.getLogger().isEnabled(LOG_CHANNEL, Logger.DEBUG) ) 182 token.getLogger().log("<== "+req.getMethod()+" end: "+sdf.format(new Date (System.currentTimeMillis()))+" ["+Thread.currentThread().getName()+"]", LOG_CHANNEL, Logger.DEBUG); 183 184 ConnectionDispenser.terminateConnection(); 185 CacheFactory.getInstance().syncCachesNow(); 186 } 187 188 } 189 190 private boolean isCollection(NamespaceAccessToken token, HttpServletRequest req) { 191 SlideToken slideToken = new SlideTokenWrapper(WebdavUtils.getSlideToken(req)); 192 slideToken.setForceSecurity(false); 193 slideToken.setForceLock(false); 194 return WebdavUtils.isCollection(token, slideToken, WebdavUtils.getRelativePath(req, (WebdavServletConfig)getServletConfig())); 195 } 196 197 201 public void init(ServletConfig config) 202 throws ServletException { 203 204 JahiaWebdavServletConfig webdavServletConfig = new JahiaWebdavServletConfig(config); 205 webdavServletConfig.setTransformDirnames(Jahia.getSettings().isTransformDirnames()); 206 webdavServletConfig.setTransformFilenames(Jahia.getSettings().isTransformFilenames()); 207 208 super.init(webdavServletConfig); 209 210 212 ConnectionDispenser.terminateConnection(); 213 } 214 215 216 219 public void init() 220 throws ServletException { 221 222 if (!isDomLevel2Parser()) { 223 log("======================================================"); 224 log("!!! Unable to start Slide Servlet !!!"); 225 log("------------------------------------------------------"); 226 log("======================================================"); 227 log("You are using using an incorrect older XML parser"); 228 log("that doesn't provide Element::getElementsByTagNameNS"); 229 log("consult the documentation for a list of valid XML parsers."); 230 log("======================================================"); 231 throw new ServletException ("Invalid XML parser"); 232 } 233 234 String value; 235 236 value = getInitParameter("directory-browsing"); 239 if (value != null) { 240 if (value.startsWith("/")) { 241 directoryBrowsingTemplate = 242 getServletContext().getRequestDispatcher(value); 243 if (directoryBrowsingTemplate == null) { 244 directoryBrowsing = false; 245 } 246 } else { 247 directoryBrowsing = Boolean.valueOf(value).booleanValue(); 248 } 249 } 250 251 value = getInitParameter("authenticate"); 252 if (value != null) { 253 authenticate = new Boolean (value).booleanValue(); 254 } 255 } 256 257 258 261 public void destroy() { 262 } 263 264 265 266 268 269 272 protected void doGet(HttpServletRequest req, HttpServletResponse res) 273 throws ServletException , IOException { 274 275 276 if (directoryBrowsing) { 277 278 NamespaceAccessToken token = (NamespaceAccessToken) req.getAttribute(ATTRIBUTE_NAME); 279 280 if (directoryBrowsingTemplate != null) { 281 req.setAttribute("org.apache.slide.NamespaceName", 283 token.getName()); 284 req.setAttribute("slide_namespace", token.getName()); 286 directoryBrowsingTemplate.forward(req, res); 287 } else { 288 try { 289 DirectoryIndexGenerator directoryIndexGenerator = new DirectoryIndexGenerator(token, (WebdavServletConfig) getServletConfig()); 290 SlideToken slideToken = new SlideTokenWrapper(WebdavUtils.getSlideToken(req)); 291 directoryIndexGenerator.generate(req, res, slideToken); 292 } catch (AccessDeniedException e) { 293 if (req.getUserPrincipal() == null) { 294 res.addHeader("WWW-Authenticate", "BASIC realm=\"" + ((NamespaceAccessToken) req.getAttribute(HttpRequestWrapper.TOKEN_ATTRIBUTE)).getName() + "\""); 295 res.sendError(HttpServletResponse.SC_UNAUTHORIZED); 296 } else { 297 res.setStatus(WebdavStatus.SC_FORBIDDEN); 298 RequestDispatcher r = req.getRequestDispatcher("/jsp/jahia/errors/error_403.jsp"); 299 r.include(req,res); 300 } 301 } catch (ObjectNotFoundException e) { 302 res.sendError(WebdavStatus.SC_NOT_FOUND); 303 } catch (LinkedObjectNotFoundException e) { 304 res.sendError(WebdavStatus.SC_NOT_FOUND); 305 } catch (SlideException e) { 306 res.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR); 307 } 308 } 309 } else { 310 res.setStatus(WebdavStatus.SC_FORBIDDEN); 311 RequestDispatcher r = req.getRequestDispatcher("/jsp/jahia/errors/error_403.jsp"); 312 r.include(req,res); 313 } 314 } 315 316 317 318 private WebdavMethod createMethod(NamespaceAccessToken token, String name) { 319 WebdavServletConfig config = (WebdavServletConfig)getServletConfig(); 320 321 if ((config == null) || (token == null)) { 322 throw new IllegalStateException (); 323 } 324 325 if (name.equals("GET")) { 326 return new GetMethod(token, config) { 327 protected void sendError( int statusCode, Throwable t ) { 328 if (statusCode == WebdavStatus.SC_FORBIDDEN) { 329 resp.setStatus(WebdavStatus.SC_FORBIDDEN); 330 RequestDispatcher r = req.getRequestDispatcher("/jsp/jahia/errors/error_403.jsp"); 331 try { 332 r.include(req,resp); 333 } catch (Exception e) { 334 super.sendError(statusCode, t); 335 } 336 } else { 337 super.sendError(statusCode, t); 338 } 339 } 340 }; 341 } else if (name.equals("PROPFIND")) { 342 return new PropFindMethod(token, config); 343 } else if (name.equals("HEAD")) { 344 return new HeadMethod(token, config); 345 } else if (name.equals("LOCK")) { 346 return new LockMethod(token, config); 347 } else if (name.equals("UNLOCK")) { 348 return new UnlockMethod(token, config); 349 } else if (name.equals("OPTIONS")) { 350 return new OptionsMethod(token, config); 351 } else if (name.equals("PUT")) { 352 return new PutMethod(token, config); 353 } else if (name.equals("MKCOL")) { 354 return new MkcolMethod(token, config); 355 } else if (name.equals("POST")) { 356 return new PostMethod(token, config); 357 } else if (name.equals("COPY")) { 358 return new CopyMethod(token, config); 359 } else if (name.equals("MOVE")) { 360 return new MoveMethod(token, config); 361 } else if (name.equals("DELETE")) { 362 return new DeleteMethod(token, config); 363 } else if (name.equals("PROPPATCH")) { 364 return new PropPatchMethod(token, config); 365 } else if (name.equals("REPORT")) { 366 return new ReportMethod(token, config); 367 } else { 368 if (Configuration.useIntegratedSecurity()) { 369 if (name.equals("ACL")) { 370 return new AclMethod(token, config); 371 } 372 } 373 if (Configuration.useSearch()) { 374 if (name.equals("SEARCH")) { 375 return new SearchMethod(token, config); 376 } 377 } 378 if (Configuration.useVersionControl()) { 379 if (name.equals("VERSION-CONTROL")) { 380 return new VersionControlMethod(token, config); 381 } else if (name.equals("CHECKIN")) { 382 return new CheckinMethod(token, config); 383 } else if (name.equals("CHECKOUT")) { 384 return new CheckoutMethod(token, config); 385 } else if (name.equals("UNCHECKOUT")) { 386 return new UncheckoutMethod(token, config); 387 } else if (name.equals("MKWORKSPACE")) { 388 return new MkworkspaceMethod(token, config); 389 } else if (name.equals("LABEL")) { 390 return new LabelMethod(token, config); 391 } else if (name.equals("UPDATE")) { 392 return new UpdateMethod(token, config); 393 } 394 } 395 if (Configuration.useGlobalBinding()) { 396 if (name.equals("BIND")) { 397 return new BindMethod(token, config); 398 } else if (name.equals("UNBIND")) { 399 return new UnbindMethod(token, config); 400 } else if (name.equals("REBIND")) { 401 return new RebindMethod(token, config); 402 } 403 } 404 } 405 406 return null; 407 } 408 409 410 static boolean isDomLevel2Parser() { 411 try { 412 return DocumentBuilderFactory.newInstance().newDocumentBuilder() 413 .getDOMImplementation().hasFeature("Core", "2.0"); 414 } catch (ParserConfigurationException e) { 415 return false; 416 } catch (FactoryConfigurationError e) { 417 return false; 418 } 419 } 420 } 421 | Popular Tags |