001/* 002 * Copyright 2012-2017 the original author or authors. 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 017package org.springframework.boot.devtools.restart.server; 018 019import java.io.IOException; 020import java.io.ObjectInputStream; 021 022import org.apache.commons.logging.Log; 023import org.apache.commons.logging.LogFactory; 024 025import org.springframework.boot.devtools.restart.classloader.ClassLoaderFiles; 026import org.springframework.http.HttpStatus; 027import org.springframework.http.server.ServerHttpRequest; 028import org.springframework.http.server.ServerHttpResponse; 029import org.springframework.util.Assert; 030 031/** 032 * A HTTP server that can be used to upload updated {@link ClassLoaderFiles} and trigger 033 * restarts. 034 * 035 * @author Phillip Webb 036 * @since 1.3.0 037 * @see RestartServer 038 */ 039public class HttpRestartServer { 040 041 private static final Log logger = LogFactory.getLog(HttpRestartServer.class); 042 043 private final RestartServer server; 044 045 /** 046 * Create a new {@link HttpRestartServer} instance. 047 * @param sourceFolderUrlFilter the source filter used to link remote folder to the 048 * local classpath 049 */ 050 public HttpRestartServer(SourceFolderUrlFilter sourceFolderUrlFilter) { 051 Assert.notNull(sourceFolderUrlFilter, "SourceFolderUrlFilter must not be null"); 052 this.server = new RestartServer(sourceFolderUrlFilter); 053 } 054 055 /** 056 * Create a new {@link HttpRestartServer} instance. 057 * @param restartServer the underlying restart server 058 */ 059 public HttpRestartServer(RestartServer restartServer) { 060 Assert.notNull(restartServer, "RestartServer must not be null"); 061 this.server = restartServer; 062 } 063 064 /** 065 * Handle a server request. 066 * @param request the request 067 * @param response the response 068 * @throws IOException in case of I/O errors 069 */ 070 public void handle(ServerHttpRequest request, ServerHttpResponse response) 071 throws IOException { 072 try { 073 Assert.state(request.getHeaders().getContentLength() > 0, "No content"); 074 ObjectInputStream objectInputStream = new ObjectInputStream( 075 request.getBody()); 076 ClassLoaderFiles files = (ClassLoaderFiles) objectInputStream.readObject(); 077 objectInputStream.close(); 078 this.server.updateAndRestart(files); 079 response.setStatusCode(HttpStatus.OK); 080 } 081 catch (Exception ex) { 082 logger.warn("Unable to handler restart server HTTP request", ex); 083 response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); 084 } 085 } 086 087}