All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.h2.plus.H2Server Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2016-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.h2.plus;

import java.io.IOException;
import java.net.ServerSocket;
import java.nio.file.Files;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.h2.plus.exception.H2ServerException;
import org.h2.tools.Server;
import org.h2.util.StringUtils;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.Synchronized;

/**
 * H2 server
 */
public class H2Server {
	
	/**
	 * Lock object
	 */
	private final Object lock = new Object();
	
	/**
	 * {@link Server}
	 */
	private Server delegate;
	
	/**
	 * Get running port
	 * 
	 * @return running port
	 */
	public int getPort() {
		
		return this.delegate.getPort();
	}
	
	/**
	 * Constructor
	 * 
	 * @param delegate {@link Server}
	 */
	protected H2Server(@NonNull Server delegate) {
		
		this.delegate = delegate;
	}
	
	/**
	 * Get {@link Builder}
	 * 
	 * @return {@link Builder}
	 */
	public static Builder builder() {
		
		return new Builder();
	}
	
	/**
	 * Start server
	 * 
	 * @return {@link H2Server}
	 * @throws H2ServerException if failed to start
	 */
	@Synchronized("lock")
	public H2Server start() throws H2ServerException {
		
		if (this.isRunning()) {
			
			throw new H2ServerException("Server is already running");
		}
		
		try {
			
			this.delegate.start();
			
			return this;
		}
		catch (SQLException e) {
			
			throw new H2ServerException("Failed to start server", e);
		}
	}
	
	/**
	 * Stop server
	 * 
	 * @return {@link H2Server}
	 * @throws H2ServerException if failed to stop
	 */
	@Synchronized("lock")
	public H2Server stop() throws H2ServerException {
		
		if (!this.isRunning()) {
			
			throw new H2ServerException("Server is not running");
		}
		
		this.delegate.stop();
		
		return this;
	}
	
	/**
	 * Check server is running
	 * 
	 * @return {@code true} if server is running
	 */
	@Synchronized("lock")
	public boolean isRunning() {
		
		return this.delegate.isRunning(false);
	}
	
	/**
	 * Builder
	 */
	@NoArgsConstructor(access = AccessLevel.PROTECTED)
	public static class Builder {
		
		/**
		 * Port
		 */
		private int port;
		
		/**
		 * Set port
		 * 
		 * @param port port
		 * @return {@link Builder}
		 */
		public Builder port(int port) {
			
			this.port = port;
			
			return this;
		}
		
		/**
		 * Base directory
		 */
		private String baseDir;
		
		/**
		 * Set base directory
		 * 
		 * @param baseDir base directory
		 * @return {@link Builder}
		 */
		public Builder baseDir(String baseDir) {
			
			this.baseDir = baseDir;
			
			return this;
		}
		
		/**
		 * Allow others
		 */
		private boolean allowOthers;
		
		/**
		 * Set allow others
		 * 
		 * @param allowOthers allow others
		 * @return {@link Builder}
		 */
		public Builder allowOthers(boolean allowOthers) {
			
			this.allowOthers = allowOthers;
			
			return this;
		}
		
		/**
		 * Daemon
		 */
		private boolean daemon = true;
		
		/**
		 * Set daemon
		 * 
		 * @param daemon daemon
		 * @return {@link Builder}
		 */
		public Builder daemon(boolean daemon) {
			
			this.daemon = daemon;
			
			return this;
		}
		
		/**
		 * Build {@link H2Server}
		 * 
		 * @return {@link H2Server}
		 * @throws H2ServerException if failed to build
		 */
		public H2Server build() throws H2ServerException {
			
			// Detect parameters
			int port = this.port;
			
			if (port == 0) {
				
				port = this.detectFreePort();
			}
			
			String baseDir = this.baseDir;
			
			if (StringUtils.isNullOrEmpty(baseDir)) {
				
				baseDir = this.detectBaseDir();
			}
			
			// Create arguments
			List args = new ArrayList<>();
			args.add("-tcp");
			args.add("-tcpPort");
			args.add(String.valueOf(port));
			args.add("-baseDir");
			args.add(baseDir);
			
			if (this.allowOthers) {
				
				args.add("-tcpAllowOthers");
			}
			
			if (this.daemon) {
				
				args.add("-tcpDaemon");
			}
			
			// Create server
			try {
				
				return new H2Server(Server.createTcpServer(args.toArray(new String[0])));
			}
			catch (SQLException e) {
				
				throw new H2ServerException("Failed to build H2 server", e);
			}
		}
		
		/**
		 * Detect free port
		 * 
		 * @return port
		 * @throws H2ServerException if failed to detect
		 */
		protected int detectFreePort() throws H2ServerException {
			
			try (ServerSocket socket = new ServerSocket(0)) {
				
				int port = socket.getLocalPort();
				
				socket.setReuseAddress(true);
				
				return port;
			}
			catch (IOException e) {
				
				throw new H2ServerException("Failed to detect free port", e);
			}
		}
		
		/**
		 * Detect base directory
		 * 
		 * @return base directory
		 * @throws H2ServerException if failed to detect
		 */
		protected String detectBaseDir() throws H2ServerException {
			
			try {
				
				return Files.createTempDirectory("H2-").toString();
			}
			catch (IOException e) {
				
				throw new H2ServerException("Failed to detect base directory", e);
			}
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy