001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017//======================================================================== 018//Copyright 2007 CSC - Scientific Computing Ltd. 019//======================================================================== 020package org.apache.activemq.util; 021 022 023import java.io.File; 024import java.io.FileOutputStream; 025import java.io.IOException; 026import java.net.HttpURLConnection; 027import java.net.URL; 028 029import javax.servlet.Filter; 030import javax.servlet.FilterChain; 031import javax.servlet.FilterConfig; 032import javax.servlet.ServletException; 033import javax.servlet.ServletRequest; 034import javax.servlet.ServletResponse; 035import javax.servlet.UnavailableException; 036import javax.servlet.http.HttpServletRequest; 037import javax.servlet.http.HttpServletResponse; 038 039import org.slf4j.Logger; 040import org.slf4j.LoggerFactory; 041 042 043/** 044 * <p> 045 * Adds support for HTTP PUT, MOVE and DELETE methods. If init parameters 046 * read-permission-role and write-permission-role are defined then all requests 047 * are authorized using the defined roles. Also GET methods are authorized. 048 * </p> 049 * 050 * @author Aleksi Kallio 051 */ 052public class RestFilter implements Filter { 053 private static final Logger LOG = LoggerFactory.getLogger(RestFilter.class); 054 055 private static final String HTTP_HEADER_DESTINATION = "Destination"; 056 private static final String HTTP_METHOD_MOVE = "MOVE"; 057 private static final String HTTP_METHOD_PUT = "PUT"; 058 private static final String HTTP_METHOD_GET = "GET"; 059 private static final String HTTP_METHOD_DELETE = "DELETE"; 060 061 private String readPermissionRole; 062 private String writePermissionRole; 063 private FilterConfig filterConfig; 064 065 public void init(FilterConfig filterConfig) throws UnavailableException { 066 this.filterConfig = filterConfig; 067 readPermissionRole = filterConfig.getInitParameter("read-permission-role"); 068 writePermissionRole = filterConfig.getInitParameter("write-permission-role"); 069 } 070 071 private File locateFile(HttpServletRequest request) { 072 return new File(filterConfig.getServletContext().getRealPath(request.getServletPath()), request.getPathInfo()); 073 } 074 075 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 076 if (!(request instanceof HttpServletRequest && response instanceof HttpServletResponse)) { 077 if (LOG.isDebugEnabled()) { 078 LOG.debug("request not HTTP, can not understand: " + request.toString()); 079 } 080 chain.doFilter(request, response); 081 return; 082 } 083 084 HttpServletRequest httpRequest = (HttpServletRequest)request; 085 HttpServletResponse httpResponse = (HttpServletResponse)response; 086 087 if (httpRequest.getMethod().equals(HTTP_METHOD_MOVE)) { 088 doMove(httpRequest, httpResponse); 089 } else if (httpRequest.getMethod().equals(HTTP_METHOD_PUT)) { 090 doPut(httpRequest, httpResponse); 091 } else if (httpRequest.getMethod().equals(HTTP_METHOD_GET)) { 092 if (checkGet(httpRequest, httpResponse)) { 093 chain.doFilter(httpRequest, httpResponse); // actual processing 094 // done elsewhere 095 } 096 } else if (httpRequest.getMethod().equals(HTTP_METHOD_DELETE)) { 097 doDelete(httpRequest, httpResponse); 098 } else { 099 chain.doFilter(httpRequest, httpResponse); 100 } 101 } 102 103 protected void doMove(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 104 if (LOG.isDebugEnabled()) { 105 LOG.debug("RESTful file access: MOVE request for " + request.getRequestURI()); 106 } 107 108 if (writePermissionRole != null && !request.isUserInRole(writePermissionRole)) { 109 response.sendError(HttpURLConnection.HTTP_FORBIDDEN); 110 return; 111 } 112 113 File file = locateFile(request); 114 String destination = request.getHeader(HTTP_HEADER_DESTINATION); 115 116 if (destination == null) { 117 response.sendError(HttpURLConnection.HTTP_BAD_REQUEST, "Destination header not found"); 118 return; 119 } 120 121 try { 122 URL destinationUrl = new URL(destination); 123 IOHelper.copyFile(file, new File(destinationUrl.getFile())); 124 IOHelper.deleteFile(file); 125 } catch (IOException e) { 126 response.sendError(HttpURLConnection.HTTP_INTERNAL_ERROR); // file 127 // could 128 // not 129 // be 130 // moved 131 return; 132 } 133 134 response.setStatus(HttpURLConnection.HTTP_NO_CONTENT); // we return no 135 // content 136 } 137 138 protected boolean checkGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 139 if (LOG.isDebugEnabled()) { 140 LOG.debug("RESTful file access: GET request for " + request.getRequestURI()); 141 } 142 143 if (readPermissionRole != null && !request.isUserInRole(readPermissionRole)) { 144 response.sendError(HttpURLConnection.HTTP_FORBIDDEN); 145 return false; 146 } else { 147 return true; 148 } 149 } 150 151 protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 152 if (LOG.isDebugEnabled()) { 153 LOG.debug("RESTful file access: PUT request for " + request.getRequestURI()); 154 } 155 156 if (writePermissionRole != null && !request.isUserInRole(writePermissionRole)) { 157 response.sendError(HttpURLConnection.HTTP_FORBIDDEN); 158 return; 159 } 160 161 File file = locateFile(request); 162 163 if (file.exists()) { 164 boolean success = file.delete(); // replace file if it exists 165 if (!success) { 166 response.sendError(HttpURLConnection.HTTP_INTERNAL_ERROR); // file 167 // existed 168 // and 169 // could 170 // not 171 // be 172 // deleted 173 return; 174 } 175 } 176 177 FileOutputStream out = new FileOutputStream(file); 178 try { 179 IOHelper.copyInputStream(request.getInputStream(), out); 180 } catch (IOException e) { 181 LOG.warn("Exception occured" , e); 182 throw e; 183 } finally { 184 out.close(); 185 } 186 187 response.setStatus(HttpURLConnection.HTTP_NO_CONTENT); // we return no 188 // content 189 } 190 191 protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 192 if (LOG.isDebugEnabled()) { 193 LOG.debug("RESTful file access: DELETE request for " + request.getRequestURI()); 194 } 195 196 if (writePermissionRole != null && !request.isUserInRole(writePermissionRole)) { 197 response.sendError(HttpURLConnection.HTTP_FORBIDDEN); 198 return; 199 } 200 201 File file = locateFile(request); 202 203 if (!file.exists()) { 204 response.sendError(HttpURLConnection.HTTP_NOT_FOUND); // file not 205 // found 206 return; 207 } 208 209 boolean success = IOHelper.deleteFile(file); // actual delete operation 210 211 if (success) { 212 response.setStatus(HttpURLConnection.HTTP_NO_CONTENT); // we return 213 // no 214 // content 215 } else { 216 response.sendError(HttpURLConnection.HTTP_INTERNAL_ERROR); // could 217 // not 218 // be 219 // deleted 220 // due 221 // to 222 // internal 223 // error 224 } 225 } 226 227 public void destroy() { 228 // nothing to destroy 229 } 230}