001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Gagnavarslan ehf
018 */
019package org.nuxeo.ecm.webdav.service;
020
021import java.io.IOException;
022
023import javax.servlet.Filter;
024import javax.servlet.FilterChain;
025import javax.servlet.FilterConfig;
026import javax.servlet.ServletException;
027import javax.servlet.ServletRequest;
028import javax.servlet.ServletResponse;
029import javax.servlet.http.HttpServletRequest;
030import javax.servlet.http.HttpServletResponse;
031
032import org.apache.commons.lang3.StringUtils;
033import org.apache.commons.logging.Log;
034import org.apache.commons.logging.LogFactory;
035import org.nuxeo.ecm.platform.web.common.requestcontroller.filter.BufferingHttpServletResponse;
036import org.nuxeo.runtime.transaction.TransactionHelper;
037import org.nuxeo.runtime.transaction.TransactionRuntimeException;
038
039/**
040 * Windows Integration Request filter, bound to /nuxeo. Allows Windows user agents to bind to the root as the expect
041 * (not /nuxeo/site/dav) and still work.
042 */
043public class WIRequestFilter implements Filter {
044
045    private static final Log log = LogFactory.getLog(WIRequestFilter.class);
046
047    public static final String WEBDAV_USERAGENT = "Microsoft-WebDAV-MiniRedir";
048
049    public static final String MSOFFICE_USERAGENT = "Microsoft Office Existence Discovery";
050
051    public static final String BACKEND_KEY = "org.nuxeo.ecm.webdav.service.backend";
052
053    @Override
054    public void init(FilterConfig filterConfig) throws ServletException {
055    }
056
057    @Override
058    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
059            ServletException {
060
061        HttpServletRequest httpRequest = (HttpServletRequest) request;
062        HttpServletResponse httpResponse = (HttpServletResponse) response;
063
064        if (!isWIRequest(httpRequest)) {
065            chain.doFilter(request, response);
066            return;
067        }
068
069        // do what WebEngineFilter does:
070        // - start a transaction
071        // - do response buffering
072        boolean txStarted = false;
073        boolean ok = false;
074        try {
075            if (!TransactionHelper.isTransactionActive()) {
076                txStarted = TransactionHelper.startTransaction();
077                if (!txStarted) {
078                    throw new ServletException("A transaction is needed.");
079                }
080                response = new BufferingHttpServletResponse(httpResponse);
081            }
082            chain.doFilter(request, response);
083            ok = true;
084        } finally {
085            if (txStarted) {
086                try {
087                    if (!ok) {
088                        TransactionHelper.setTransactionRollbackOnly();
089                    }
090                    TransactionHelper.commitOrRollbackTransaction();
091                } catch (TransactionRuntimeException e) {
092                    // commit failed, report this to the client before stopping buffering
093                    ((HttpServletResponse) response).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
094                            e.getMessage());
095                    log.error(e); // don't rethrow inside finally
096                } finally {
097                    ((BufferingHttpServletResponse) response).stopBuffering();
098                }
099            }
100        }
101    }
102
103    @Override
104    public void destroy() {
105    }
106
107    private boolean isWIRequest(HttpServletRequest request) {
108        String ua = request.getHeader("User-Agent");
109        return StringUtils.isNotEmpty(ua) && (ua.contains(WEBDAV_USERAGENT) || ua.contains(MSOFFICE_USERAGENT));
110    }
111
112}