TCP 서버 모드 추가
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
package com.eactive.testmaster.socket;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.util.concurrent.DefaultThreadFactory;
|
||||
|
||||
public class NettyServer {
|
||||
private final int port;
|
||||
private EventLoopGroup bossGroup;
|
||||
private EventLoopGroup workerGroup;
|
||||
private Channel serverChannel;
|
||||
private volatile boolean isInitialized = false;
|
||||
private final String script;
|
||||
|
||||
public NettyServer(int port, String script) {
|
||||
this.port = port;
|
||||
this.script = script;
|
||||
}
|
||||
|
||||
public synchronized void start() throws InterruptedException {
|
||||
if (isInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Use custom thread factories to avoid naming conflicts
|
||||
bossGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("netty-boss"));
|
||||
workerGroup = new NioEventLoopGroup(
|
||||
Runtime.getRuntime().availableProcessors() * 2,
|
||||
new DefaultThreadFactory("netty-worker")
|
||||
);
|
||||
|
||||
ServerBootstrap serverBootstrap = new ServerBootstrap();
|
||||
serverBootstrap
|
||||
.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.option(ChannelOption.SO_BACKLOG, 128)
|
||||
.childOption(ChannelOption.SO_KEEPALIVE, true)
|
||||
.childHandler(new ChannelInitializer<Channel>() {
|
||||
@Override
|
||||
protected void initChannel(Channel ch) {
|
||||
ch.pipeline().addLast(new NettySocketHandler(script));
|
||||
}
|
||||
});
|
||||
|
||||
// Bind and wait for the server socket
|
||||
ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
|
||||
if (!channelFuture.isSuccess()) {
|
||||
throw new RuntimeException("Failed to bind to port " + port);
|
||||
}
|
||||
|
||||
serverChannel = channelFuture.channel();
|
||||
isInitialized = true;
|
||||
|
||||
System.out.println("Netty server started on port " + port);
|
||||
} catch (Exception e) {
|
||||
// Clean up resources if initialization fails
|
||||
stop();
|
||||
throw new RuntimeException("Failed to start Netty server", e);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void stop() throws InterruptedException {
|
||||
try {
|
||||
if (serverChannel != null) {
|
||||
serverChannel.close().sync();
|
||||
serverChannel = null;
|
||||
}
|
||||
} finally {
|
||||
// Always attempt to shut down the event loop groups
|
||||
try {
|
||||
if (workerGroup != null) {
|
||||
workerGroup.shutdownGracefully().sync();
|
||||
workerGroup = null;
|
||||
}
|
||||
} finally {
|
||||
if (bossGroup != null) {
|
||||
bossGroup.shutdownGracefully().sync();
|
||||
bossGroup = null;
|
||||
}
|
||||
}
|
||||
isInitialized = false;
|
||||
System.out.println("Netty server stopped on port " + port);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package com.eactive.testmaster.socket;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.util.ReferenceCountUtil;
|
||||
import javax.script.Invocable;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class NettySocketHandler extends ChannelInboundHandlerAdapter {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(NettySocketHandler.class);
|
||||
private final ScriptEngine engine;
|
||||
|
||||
public NettySocketHandler(String scriptContent) {
|
||||
ScriptEngineManager manager = new ScriptEngineManager();
|
||||
this.engine = manager.getEngineByName("nashorn");
|
||||
try {
|
||||
engine.eval(scriptContent);
|
||||
} catch (ScriptException e) {
|
||||
logger.error("Failed to initialize script", e);
|
||||
throw new RuntimeException("Script initialization failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) {
|
||||
logger.info("Client connected: {}", ctx.channel().remoteAddress());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) {
|
||||
logger.info("Client disconnected: {}", ctx.channel().remoteAddress());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) {
|
||||
ByteBuf in = (ByteBuf) msg;
|
||||
try {
|
||||
logger.debug("Received new message from client: {}", ctx.channel().remoteAddress());
|
||||
logger.debug("Total readable bytes: {}", in.readableBytes());
|
||||
|
||||
// Read the entire message as it comes
|
||||
byte[] messageBytes = new byte[in.readableBytes()];
|
||||
in.readBytes(messageBytes);
|
||||
String message = new String(messageBytes);
|
||||
|
||||
logger.debug("Message processing details:");
|
||||
logger.debug("- Raw message: {}", message);
|
||||
logger.debug("- Hex dump: {}", bytesToHex(messageBytes));
|
||||
|
||||
// Process the message, removing the length prefix
|
||||
String messageContent = message.substring(4);
|
||||
logger.debug("- Message content (without length): {}", messageContent);
|
||||
|
||||
String result;
|
||||
try {
|
||||
logger.debug("Executing script processor for message");
|
||||
Invocable invocable = (Invocable) engine;
|
||||
Object jsResult = invocable.invokeFunction("processMessage", messageContent);
|
||||
result = String.valueOf(jsResult);
|
||||
logger.debug("Script processing successful. Result: {}", result);
|
||||
} catch (ScriptException | NoSuchMethodException e) {
|
||||
logger.error("Script execution error", e);
|
||||
result = "Error: " + e.getMessage();
|
||||
logger.error("Script execution failed. Using error message as result: {}", result);
|
||||
}
|
||||
|
||||
// Format response with length prefix
|
||||
byte[] responseBytes = result.getBytes();
|
||||
String lengthPrefix = String.format("%04d", responseBytes.length + 4);
|
||||
logger.debug("Preparing response:");
|
||||
logger.debug("- Response content: {}", result);
|
||||
logger.debug("- Response length: {}", responseBytes.length);
|
||||
logger.debug("- Length prefix: {}", lengthPrefix);
|
||||
|
||||
ByteBuf response = ctx.alloc().buffer(4 + responseBytes.length);
|
||||
response.writeBytes(lengthPrefix.getBytes());
|
||||
response.writeBytes(responseBytes);
|
||||
|
||||
logger.debug("Sending response to client: {}", ctx.channel().remoteAddress());
|
||||
logger.debug("- Total response size: {} bytes", 4 + responseBytes.length);
|
||||
ctx.writeAndFlush(response);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Error processing message from client: {}", ctx.channel().remoteAddress(), e);
|
||||
logger.error("Error occurred at reader index: {}", in.readerIndex());
|
||||
} finally {
|
||||
logger.debug("Releasing ByteBuf resources");
|
||||
ReferenceCountUtil.release(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to convert byte array to hexadecimal string for logging
|
||||
*/
|
||||
private String bytesToHex(byte[] bytes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : bytes) {
|
||||
sb.append(String.format("%02X ", b));
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
logger.error("Channel error:", cause);
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.eactive.testmaster.socket.controller;
|
||||
|
||||
import com.eactive.testmaster.socket.entity.NettyServerEntity;
|
||||
import com.eactive.testmaster.socket.service.NettyServerService;
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/mgmt/socket")
|
||||
public class NettyServerController {
|
||||
|
||||
private static final String NETTY_SERVER = "nettyServer";
|
||||
private static final String NETTY_SERVER_LIST_VIEW = "page/socket/serverList";
|
||||
private static final String NETTY_SERVER_EDIT = "page/socket/serverEdit";
|
||||
private static final String REDIRECT_TO_LIST = "redirect:/mgmt/socket/list_view.do";
|
||||
|
||||
private final NettyServerService nettyServerService;
|
||||
|
||||
public NettyServerController(NettyServerService nettyServerService) {
|
||||
this.nettyServerService = nettyServerService;
|
||||
}
|
||||
|
||||
@GetMapping("/list_view.do")
|
||||
@Secured("ROLE_MANAGE_NETTY")
|
||||
public ModelAndView listView(@ModelAttribute("serverSearch") NettyServerSearch serverSearch,
|
||||
Pageable pageable) {
|
||||
ModelAndView mav = new ModelAndView(NETTY_SERVER_LIST_VIEW);
|
||||
Page<NettyServerEntity> page = nettyServerService.findAll(serverSearch.buildSpecification(), pageable);
|
||||
mav.addObject("page", page);
|
||||
mav.addObject("pageable", pageable);
|
||||
mav.addObject("modelSearch", serverSearch);
|
||||
return mav;
|
||||
}
|
||||
|
||||
@GetMapping("/create_view.do")
|
||||
@Secured("ROLE_MANAGE_NETTY")
|
||||
public ModelAndView createView() {
|
||||
ModelAndView mav = new ModelAndView(NETTY_SERVER_EDIT);
|
||||
mav.addObject(NETTY_SERVER, new NettyServerEntity());
|
||||
return mav;
|
||||
}
|
||||
|
||||
@GetMapping("/update_view.do")
|
||||
@Secured("ROLE_MANAGE_NETTY")
|
||||
public ModelAndView updateView(@RequestParam("id") Long id) {
|
||||
ModelAndView mav = new ModelAndView(NETTY_SERVER_EDIT);
|
||||
NettyServerEntity server = nettyServerService.findById(id);
|
||||
mav.addObject(NETTY_SERVER, server);
|
||||
return mav;
|
||||
}
|
||||
|
||||
@PostMapping("/register.do")
|
||||
@Secured("ROLE_MANAGE_NETTY")
|
||||
public String register(@Valid @ModelAttribute(NETTY_SERVER) NettyServerEntity server,
|
||||
BindingResult bindingResult,
|
||||
ModelMap model) {
|
||||
if (bindingResult.hasErrors()) {
|
||||
model.addAttribute(NETTY_SERVER, server);
|
||||
return NETTY_SERVER_EDIT;
|
||||
}
|
||||
|
||||
try {
|
||||
nettyServerService.createServer(server);
|
||||
return REDIRECT_TO_LIST;
|
||||
} catch (Exception e) {
|
||||
bindingResult.rejectValue("port", "error.port.inuse",
|
||||
"Port is already in use or invalid");
|
||||
model.addAttribute(NETTY_SERVER, server);
|
||||
return NETTY_SERVER_EDIT;
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/update.do")
|
||||
@Secured("ROLE_MANAGE_NETTY")
|
||||
public String update(@RequestParam("id") Long id,
|
||||
@Valid @ModelAttribute(NETTY_SERVER) NettyServerEntity server,
|
||||
BindingResult bindingResult,
|
||||
ModelMap model) {
|
||||
if (bindingResult.hasErrors()) {
|
||||
model.addAttribute(NETTY_SERVER, server);
|
||||
return NETTY_SERVER_EDIT;
|
||||
}
|
||||
|
||||
try {
|
||||
nettyServerService.updateServer(id, server);
|
||||
return REDIRECT_TO_LIST;
|
||||
} catch (Exception e) {
|
||||
bindingResult.rejectValue("port", "error.update.failed",
|
||||
"Failed to update server");
|
||||
model.addAttribute(NETTY_SERVER, server);
|
||||
return NETTY_SERVER_EDIT;
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/delete.do")
|
||||
@Secured("ROLE_MANAGE_NETTY")
|
||||
public String delete(@RequestParam("checkedIdForDel") List<String> ids) {
|
||||
for (String id : ids) {
|
||||
try {
|
||||
nettyServerService.deleteServer(Long.parseLong(id));
|
||||
} catch (Exception e) {
|
||||
// Log error but continue with other deletions
|
||||
}
|
||||
}
|
||||
return REDIRECT_TO_LIST;
|
||||
}
|
||||
|
||||
@PostMapping("/servers/{id}/start")
|
||||
@Secured("ROLE_MANAGE_NETTY")
|
||||
public ResponseEntity<Void> startServer(@PathVariable Long id) {
|
||||
try {
|
||||
nettyServerService.startServer(id);
|
||||
return ResponseEntity.ok().build();
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.internalServerError().build();
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/servers/{id}/stop")
|
||||
@Secured("ROLE_MANAGE_NETTY")
|
||||
public ResponseEntity<Void> stopServer(@PathVariable Long id) {
|
||||
try {
|
||||
nettyServerService.stopServer(id);
|
||||
return ResponseEntity.ok().build();
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.internalServerError().build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.eactive.testmaster.socket.controller;
|
||||
|
||||
import com.eactive.testmaster.common.search.BaseSearch;
|
||||
import com.eactive.testmaster.common.search.ColumnSearchModel;
|
||||
import com.eactive.testmaster.common.search.SearchCondition;
|
||||
import com.eactive.testmaster.common.search.SearchModel;
|
||||
import com.eactive.testmaster.socket.entity.NettyServerEntity;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class NettyServerSearch implements BaseSearch<NettyServerEntity> {
|
||||
|
||||
private String name;
|
||||
private Long port;
|
||||
|
||||
@Override
|
||||
public List<SearchModel> buildSearchCondition() {
|
||||
List<SearchModel> models = new ArrayList<>();
|
||||
models.add(new ColumnSearchModel("name", SearchCondition.LIKE, name));
|
||||
models.add(new ColumnSearchModel("port", SearchCondition.EQUAL, port));
|
||||
return models;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(Long port) {
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.eactive.testmaster.socket.entity;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Lob;
|
||||
import javax.persistence.PreUpdate;
|
||||
import javax.persistence.Table;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
@Entity
|
||||
@Table(name = "netty_servers")
|
||||
public class NettyServerEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@Column(unique = true, nullable = false)
|
||||
private Integer port;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Boolean active = true;
|
||||
|
||||
@Lob
|
||||
private String script;
|
||||
|
||||
@Type(type = "org.hibernate.type.LocalDateTimeType")
|
||||
private LocalDateTime createdAt = LocalDateTime.now();
|
||||
|
||||
|
||||
@Type(type = "org.hibernate.type.LocalDateTimeType")
|
||||
private LocalDateTime lastModified = LocalDateTime.now();
|
||||
|
||||
// Standard getters and setters
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(Integer port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public Boolean getActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(Boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(LocalDateTime createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getLastModified() {
|
||||
return lastModified;
|
||||
}
|
||||
|
||||
public void setLastModified(LocalDateTime lastModified) {
|
||||
this.lastModified = lastModified;
|
||||
}
|
||||
|
||||
@PreUpdate
|
||||
protected void onUpdate() {
|
||||
lastModified = LocalDateTime.now();
|
||||
}
|
||||
|
||||
public String getScript() {
|
||||
return script;
|
||||
}
|
||||
|
||||
public void setScript(String script) {
|
||||
this.script = script;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.eactive.testmaster.socket.repository;
|
||||
|
||||
|
||||
import com.eactive.testmaster.socket.entity.NettyServerEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface NettyServerRepository extends JpaRepository<NettyServerEntity, Long>, JpaSpecificationExecutor<NettyServerEntity> {
|
||||
|
||||
Optional<NettyServerEntity> findByPort(Integer port);
|
||||
|
||||
List<NettyServerEntity> findByActive(Boolean active);
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
package com.eactive.testmaster.socket.service;
|
||||
|
||||
import com.eactive.testmaster.socket.NettyServer;
|
||||
import com.eactive.testmaster.socket.entity.NettyServerEntity;
|
||||
import com.eactive.testmaster.socket.repository.NettyServerRepository;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
public class NettyServerService {
|
||||
private final NettyServerRepository repository;
|
||||
private final Map<Integer, NettyServer> activeServers = new HashMap<>();
|
||||
|
||||
public NettyServerService(NettyServerRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Page<NettyServerEntity> findAll(Specification<NettyServerEntity> spec, Pageable pageable) {
|
||||
return repository.findAll(spec, pageable);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public NettyServerEntity findById(Long id) {
|
||||
return repository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException("Server not found with id: " + id));
|
||||
}
|
||||
|
||||
public NettyServerEntity createServer(NettyServerEntity server) {
|
||||
validatePort(server.getPort());
|
||||
server.setActive(true);
|
||||
return repository.save(server);
|
||||
}
|
||||
|
||||
public NettyServerEntity updateServer(Long id, NettyServerEntity updatedServer) {
|
||||
NettyServerEntity existingServer = findById(id);
|
||||
|
||||
// If port is being changed, validate the new port
|
||||
if (!existingServer.getPort().equals(updatedServer.getPort())) {
|
||||
validatePort(updatedServer.getPort());
|
||||
|
||||
// Stop the server if it's running on the old port
|
||||
try {
|
||||
stopServerIfRunning(existingServer.getPort());
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException("Failed to stop server during port update", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Update all fields
|
||||
existingServer.setPort(updatedServer.getPort());
|
||||
existingServer.setActive(updatedServer.getActive());
|
||||
existingServer.setName(updatedServer.getName());
|
||||
existingServer.setScript(updatedServer.getScript()); // Add this line to update the script
|
||||
|
||||
return repository.save(existingServer);
|
||||
}
|
||||
|
||||
public void deleteServer(Long id) throws InterruptedException {
|
||||
NettyServerEntity server = findById(id);
|
||||
stopServerIfRunning(server.getPort());
|
||||
repository.deleteById(id);
|
||||
}
|
||||
|
||||
public void startServer(Long id) throws InterruptedException {
|
||||
NettyServerEntity entity = findById(id);
|
||||
|
||||
if (!entity.getActive()) {
|
||||
throw new IllegalStateException("Cannot start inactive server: " + id);
|
||||
}
|
||||
|
||||
if (!activeServers.containsKey(entity.getPort())) {
|
||||
NettyServer server = new NettyServer(entity.getPort(), entity.getScript());
|
||||
server.start();
|
||||
activeServers.put(entity.getPort(), server);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void stopServer(Long id) throws InterruptedException {
|
||||
NettyServerEntity entity = findById(id);
|
||||
stopServerIfRunning(entity.getPort());
|
||||
}
|
||||
|
||||
private void stopServerIfRunning(Integer port) throws InterruptedException {
|
||||
NettyServer server = activeServers.remove(port);
|
||||
if (server != null) {
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
// @Transactional
|
||||
// public void deactivateServer(Long id) throws InterruptedException {
|
||||
// NettyServerEntity entity = findById(id);
|
||||
// stopServerIfRunning(entity.getPort());
|
||||
// entity.setActive(false);
|
||||
// repository.save(entity);
|
||||
// }
|
||||
|
||||
// @Transactional(readOnly = true)
|
||||
// public List<NettyServerEntity> getAllServers() {
|
||||
// return repository.findAll();
|
||||
// }
|
||||
|
||||
// @Transactional(readOnly = true)
|
||||
// public List<NettyServerEntity> getActiveServers() {
|
||||
// return repository.findByActive(true);
|
||||
// }
|
||||
|
||||
// @Transactional(readOnly = true)
|
||||
// public boolean isServerRunning(Integer port) {
|
||||
// return activeServers.containsKey(port);
|
||||
// }
|
||||
|
||||
// @Transactional(readOnly = true)
|
||||
// public Map<Integer, Boolean> getServerStatuses(List<Integer> ports) {
|
||||
// Map<Integer, Boolean> statuses = new HashMap<>();
|
||||
// for (Integer port : ports) {
|
||||
// statuses.put(port, activeServers.containsKey(port));
|
||||
// }
|
||||
// return statuses;
|
||||
// }
|
||||
|
||||
private void validatePort(Integer port) {
|
||||
if (port == null) {
|
||||
throw new IllegalArgumentException("Port cannot be null");
|
||||
}
|
||||
|
||||
if (port < 1024 || port > 65535) {
|
||||
throw new IllegalArgumentException("Port must be between 1024 and 65535");
|
||||
}
|
||||
|
||||
if (port >= 5701 && port <= 5801) {
|
||||
throw new IllegalArgumentException(
|
||||
"Port " + port + " conflicts with Hazelcast port range (5701-5801)"
|
||||
);
|
||||
}
|
||||
|
||||
Optional<NettyServerEntity> existingServer = repository.findByPort(port);
|
||||
if (existingServer.isPresent()) {
|
||||
throw new IllegalArgumentException("Port " + port + " is already in use");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user