apache mina开发文件传输服务器

服务器接收端
/**
 * 
 */
package org.liufei.net.file;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;

import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.dom4j.DocumentException;
import org.liufei.net.ServerConfig;
import org.liufei.util.FileDesHandler;
import org.liufei.util.entity.FileDes;

/**
 * @author 刘飞
 * 
 */
public class FileReceiveHandler extends IoHandlerAdapter {
	private static final Logger logger = Logger.getLogger(FileReceiveHandler.class) ;
	private ServerConfig config = ServerConfig.getInstance() ;

	private FileChannel fileChannel = null;

	/**
	 * 
	 */
	public FileReceiveHandler() {
	}
	
	private void initFileChannel() throws DocumentException, IOException {
		String time = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss").format(GregorianCalendar.getInstance().getTime()) ;
		File file = new File(
				config.directory(), 
				FileDesHandler.query(FileDes.FILE_DES_ID).getFileName()) ;
		
		if(!file.exists()) {
			file.createNewFile() ;
		}
		else {
			file = new File(
					config.directory(), 
					time + "_" +
					FileDesHandler.query(FileDes.FILE_DES_ID).getFileName()) ;
		}
		
		fileChannel = new FileOutputStream(file).getChannel() ;
	}
	
	private void closeFileChannel() {
		if(fileChannel != null) {
			try {
				if(fileChannel.isOpen()) {
					FileLock fileLock = fileChannel.lock() ;
					if(fileLock != null) {
						fileLock.release() ;
					}
					
					fileChannel.close() ;
					fileChannel = null ;
				}
			} catch (IOException e) {
				logger.error("文件解锁异常。", e) ;
				throw new RuntimeException("文件解锁异常。", e) ;
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.mina.core.service.IoHandlerAdapter#exceptionCaught(org.apache
	 * .mina.core.session.IoSession, java.lang.Throwable)
	 */
	@Override
	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {
		closeFileChannel() ;
		session.close(true) ;
		logger.error("file upload error .", cause) ;
		FileDesHandler.close() ;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.mina.core.service.IoHandlerAdapter#messageReceived(org.apache
	 * .mina.core.session.IoSession, java.lang.Object)
	 */
	@Override
	public void messageReceived(IoSession session, Object message)
			throws Exception {
		if(fileChannel == null){
			try {
				initFileChannel() ;
			} catch (DocumentException e) {
				logger.error("reading xml config error.", e) ;
			} catch (IOException e) {
				logger.error("init FileChannel error.", e) ;
			}
		}
		
		logger.debug("Message From IP >>> " + session.getRemoteAddress().toString() + " <<<") ;
		IoBuffer ib = (IoBuffer) message;
		logger.debug("\n\t\tDATA >>> " + message.toString() + "\n\t\tDATA SIZE >>> " + ib.capacity() + "\n") ;
		fileChannel.write(ib.buf());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.mina.core.service.IoHandlerAdapter#messageSent(org.apache.
	 * mina.core.session.IoSession, java.lang.Object)
	 */
	@Override
	public void messageSent(IoSession session, Object message) throws Exception {
		super.messageSent(session, message);
		logger.debug("super.messageSent(IoSession session, Object message)\n\t\t >>> " + session.getRemoteAddress().toString() + " <<<") ;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.mina.core.service.IoHandlerAdapter#sessionClosed(org.apache
	 * .mina.core.session.IoSession)
	 */
	@Override
	public void sessionClosed(IoSession session) throws Exception {
		super.sessionClosed(session);
		logger.debug("super.sessionClosed(IoSession session)\n\t\t >>> " + session.getRemoteAddress().toString() + " <<<") ;
		FileDesHandler.close() ;
		closeFileChannel() ;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.mina.core.service.IoHandlerAdapter#sessionCreated(org.apache
	 * .mina.core.session.IoSession)
	 */
	@Override
	public void sessionCreated(IoSession session) throws Exception {
		super.sessionCreated(session);
		logger.debug("super.sessionCreated(IoSession session)\n\t\t >>> " + session.getRemoteAddress().toString() + " <<<") ;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.mina.core.service.IoHandlerAdapter#sessionIdle(org.apache.
	 * mina.core.session.IoSession, org.apache.mina.core.session.IdleStatus)
	 */
	@Override
	public void sessionIdle(IoSession session, IdleStatus status)
			throws Exception {
		super.sessionIdle(session, status);
		logger.debug("super.sessionIdle(IoSession session, IdleStatus status)\n\t\t >>> " + session.getRemoteAddress().toString() + " <<<") ;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.mina.core.service.IoHandlerAdapter#sessionOpened(org.apache
	 * .mina.core.session.IoSession)
	 */
	@Override
	public void sessionOpened(IoSession session) throws Exception {
		super.sessionOpened(session);
		logger.debug("super.sessionOpened(IoSession session)\n\t\t >>> " + session.getRemoteAddress().toString() + " <<<") ;
	}
}


package org.liufei.net.file;

import java.io.IOException;
import java.net.InetSocketAddress;

import org.apache.log4j.Logger;
import org.apache.mina.transport.socket.SocketAcceptor;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.liufei.net.ServerConfig;

public class FileServer {
	private static final Logger logger = Logger.getLogger(FileServer.class) ;
	private ServerConfig config = ServerConfig.getInstance() ;

	public SocketAcceptor server() {
		int port = config.port() ;
		try {
			SocketAcceptor socketAcceptor = new NioSocketAcceptor();

			socketAcceptor.getFilterChain();
			socketAcceptor.setHandler(new FileReceiveHandler());
			socketAcceptor.bind(new InetSocketAddress(port));
			logger.debug("start NET FILE SERVER success !\n\t\t HTTP PORT >>> " + port + "\n") ;
			return socketAcceptor ;
		} catch (IOException e) {
			logger.error("start NET FILE SERVER error !\n\t\t HTTP PORT >>> " + port + "\n", e) ;
			throw new RuntimeException("start NET FILE SERVER error !\n\t\t HTTP PORT >>> " + port + "\n", e) ;
		}
	}
}

客户端
package org.liufei.net.file;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;

/**
 * 
 * @author 刘飞
 * 
 */
public class FileSenderHandler extends IoHandlerAdapter {

	/**
	 * 
	 */
	public FileSenderHandler() {
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.mina.core.service.IoHandlerAdapter#exceptionCaught(org.apache
	 * .mina.core.session.IoSession, java.lang.Throwable)
	 */
	@Override
	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {
		super.exceptionCaught(session, cause);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.mina.core.service.IoHandlerAdapter#messageReceived(org.apache
	 * .mina.core.session.IoSession, java.lang.Object)
	 */
	@Override
	public void messageReceived(IoSession session, Object message)
			throws Exception {
		super.messageReceived(session, message);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.mina.core.service.IoHandlerAdapter#messageSent(org.apache.
	 * mina.core.session.IoSession, java.lang.Object)
	 */
	@Override
	public void messageSent(IoSession session, Object message) throws Exception {
		super.messageSent(session, message);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.mina.core.service.IoHandlerAdapter#sessionClosed(org.apache
	 * .mina.core.session.IoSession)
	 */
	@Override
	public void sessionClosed(IoSession session) throws Exception {
		super.sessionClosed(session);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.mina.core.service.IoHandlerAdapter#sessionCreated(org.apache
	 * .mina.core.session.IoSession)
	 */
	@Override
	public void sessionCreated(IoSession session) throws Exception {
		super.sessionCreated(session);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.mina.core.service.IoHandlerAdapter#sessionIdle(org.apache.
	 * mina.core.session.IoSession, org.apache.mina.core.session.IdleStatus)
	 */
	@Override
	public void sessionIdle(IoSession session, IdleStatus status)
			throws Exception {
		super.sessionIdle(session, status);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.mina.core.service.IoHandlerAdapter#sessionOpened(org.apache
	 * .mina.core.session.IoSession)
	 */
	@Override
	public void sessionOpened(IoSession session) throws Exception {
		super.sessionOpened(session);
	}

}
package org.liufei.net.file;

import java.io.File;
import java.io.FileInputStream;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

import org.apache.log4j.Logger;
import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.liufei.net.ClientConfig;
import org.liufei.net.util.FileDesHandler;
import org.liufei.net.util.JavaZip;
import org.liufei.net.util.entity.FileDes;

public class FileClient {
	private static final int CAPACITY = 2048 * 1000;
	private static final Logger logger = Logger.getLogger(FileClient.class) ;
	private ClientConfig config = ClientConfig.getInstance() ;
	
	private String host = "172.16.0.11";
	private int port = 8888;
	
	public static void main(String[] args) {
		logger.debug("please run new FileClient().upload(String/File)") ;
		System.out.println("please run new FileClient().upload(String/File)");
	}
	
	/**
	 * 只能一次上传一个文件
	 * @param path
	 * @return
	 */
	public boolean upload(String path) {
		return upload(new File(path)) ;
	}
	
	/**
	 * 只能一次上传一个文件
	 * @param file
	 * @return
	 */
	public boolean upload(File file) {
		if(file.isFile() && !file.isDirectory()) {
			return netFileUpload(file, FileDes.UNZIP_NO) ;
		}
		else if(file.isDirectory()){
			File zipFile = new File(file.getAbsolutePath() + ".zip");
			try {
				JavaZip.zip(file, zipFile);
				return netFileUpload(zipFile, FileDes.UNZIP_YES) ;
			} catch (Exception e) {
				logger.error("传输目录文件时压缩传输异常.", e) ;
				throw new RuntimeException("传输目录文件时压缩传输异常.", e) ;
			}
		}
		else {
			return false ;
		}
	}
	
	/**
	 * File f = new File("D:\\MyBatis 3 User Guide Simplified Chinese.pdf");
	 * 
	 * @param file
	 * @return
	 */
	private boolean netFileUpload(final File file, final int unZip_mark) {
		boolean flag = false ;
		host = config.host();
		port = config.port();
		
		NioSocketConnector connector = null ;
		ConnectFuture connectFuture = null ;
		IoSession session = null;
		
		try {
			connector = new NioSocketConnector();
			connector.getFilterChain();
			connector.setHandler(new FileSenderHandler());
			connectFuture = connector.connect(new InetSocketAddress(host, port));
			logger.debug("connect to host >>> " + host + " <<< success.") ;
			for (;;) {
				try {
					ConnectFuture future = connector.connect(new InetSocketAddress(host, port));
					future.awaitUninterruptibly();
					session = future.getSession();

					logger.debug("connect to host >>> " + host + " <<< success.") ;
					
					break;
				} catch (RuntimeIoException e) {
					logger.error("connect to host >>> " + host + " <<< error.", e) ;
					close(
							connector, e, 
							connectFuture, e,
							session, e
					) ;
					Thread.sleep(5000);
				}
			}
			
			FileInputStream in = new FileInputStream(file);
			FileChannel fileChannel = in.getChannel();
			ByteBuffer byteBuffer = ByteBuffer.allocate(CAPACITY);
			logger.debug("begin upload file >>> " + file.getAbsolutePath() + " <<<") ;
			
			FileDes fileDes = FileDesHandler.query(FileDes.FILE_DES_ID) ;
			String filePath = file.getAbsolutePath().replace(File.separatorChar, '/') ;
			if(fileDes == null) {
				fileDes = new FileDes() ;
				fileDes.setSource(filePath) ;
				fileDes.setUnZip(unZip_mark) ;
				fileDes.setId(FileDes.FILE_DES_ID) ;
				fileDes.setFileName(file.getName()) ;
				fileDes.setFileLength(file.length()) ;
				fileDes.setMark(FileDes.MARK_START) ;
				fileDes.setStatus(FileDes.STATUS_ERROR) ;
				fileDes.setEnd(FileDes.END_NO) ;
				FileDesHandler.insert(fileDes) ;
			}
			else {
				fileDes.setSource(filePath) ;
				fileDes.setUnZip(unZip_mark) ;
				fileDes.setFileName(file.getName()) ;
				fileDes.setFileLength(file.length()) ;
				fileDes.setMark(FileDes.MARK_START) ;
				fileDes.setStatus(FileDes.STATUS_ERROR) ;
				fileDes.setEnd(FileDes.END_NO) ;
				FileDesHandler.update(fileDes) ;
			}
			
			
			while (true) {
				/**
				 * 不间断发送会导致buffer异常
				 */
				Thread.sleep(1000);
				byteBuffer.clear();
				int i = fileChannel.read(byteBuffer);
				if (i == -1) {
					flag = true ;
					logger.debug("upload file >>> " + file.getAbsolutePath() + " <<< success .") ;
					
					fileDes.setFileName(file.getName()) ;
					fileDes.setFileLength(file.length()) ;
					fileDes.setSource(filePath) ;
					fileDes.setUnZip(unZip_mark) ;
					fileDes.setMark(FileDes.MARK_START) ;
					fileDes.setStatus(FileDes.STATUS_SUCESS) ;
					fileDes.setEnd(FileDes.END_YES) ;
					FileDesHandler.update(fileDes) ;
					FileDesHandler.close() ;
					close(
							connector, null, 
							connectFuture, null,
							session, null
					) ;
					if(unZip_mark == FileDes.UNZIP_YES) {
						logger.debug("delete zip file : " + file.getAbsolutePath()) ;
						file.delete() ;
					}
					break;
				}
				IoBuffer io_buffer_apache = IoBuffer.wrap(byteBuffer);
				byteBuffer.flip();
				Thread.sleep(1000);
				session.write(io_buffer_apache);
				Thread.sleep(1000);
			}
			close(
					connector, null, 
					connectFuture, null,
					session, null
			) ;
			session.close(true);

		} catch (Throwable e) {
			close(
					connector, e, 
					connectFuture, e,
					session, e
			) ;
			FileDesHandler.close() ;
			throw new RuntimeException("NET FILE SERVER UPLOAD FILE [" + file + "] [host:" + host + ", port:" + port + "] error >>>", e) ;
		}
		
		return flag ;
	}
	
	private void close(
			
			NioSocketConnector connector, 
			Throwable e1, 
			ConnectFuture connectFuture, 
			Throwable e2, 
			IoSession session, 
			Throwable e3
			
	) {
		if(connector != null) {
			if(connector.isActive()) {
				connector.dispose(true) ;
			}
			if(!connector.isDisposed()) {
				connector.dispose(true) ;
			}
			if(e1 != null) 
				logger.error("NIO Socket Connector [host:" + host + ", port:" + port + "] Dispose >>>", e1) ;
			else 
				logger.debug("NIO Socket Connector [host:" + host + ", port:" + port + "] Dispose >>>") ;
			connector = null ;
		}
		if(connectFuture != null) {
			if(connectFuture.isConnected()) {
				connectFuture.cancel() ;
			}
			if(!connectFuture.isCanceled()) {
				connectFuture.cancel() ;
			}
			connectFuture = null ;
			if(e2 != null) 
				logger.error("Connect Future [host:" + host + ", port:" + port + "] Cancel >>>", e2) ;
			else 
				logger.debug("Connect Future [host:" + host + ", port:" + port + "] Cancel >>>") ;
		}
		if(session != null) {
			if(session.isConnected()) {
				session.close(true) ;
			}
			session = null;
			if(e3 != null) 
				logger.error("IoSession [host:" + host + ", port:" + port + "] closing >>>", e3) ;
			else 
				logger.debug("IoSession [host:" + host + ", port:" + port + "] closing >>>") ;
		}
	}
}

服务器
package org.liufei.net;

import org.apache.log4j.Logger;
import org.apache.mina.transport.socket.SocketAcceptor;
import org.liufei.net.file.FileServer;
import org.liufei.net.ui.ServerManager;

public class Server {
	
	private static final Server server = new Server() ;
	private ServerConfig config = ServerConfig.getInstance() ;
	private SocketAcceptor socketAcceptor = null ;
	
	/**
	 * net file server
	 */
	private Server() {
	}
	
	public static Server getInstance() {
		return server ;
	}
	
	/**
	 * 启动一个服务并返回当前服务实例
	 * @return
	 */
	public void start(){
		try {
			socketAcceptor = new FileServer().server() ;
			if(socketAcceptor != null) {
				START_FLAG.set(START_SUCCESS) ;
				logger.debug("start NET FILE SERVER SUCCESS.") ;
			}
			else {
				START_FLAG.set(START_ERROR) ;
				logger.debug("start NET FILE SERVER ERROR.") ;
			}
		} catch (Exception e) {
			START_FLAG.set(START_ERROR) ;
			logger.error("start error message.", e) ;
			ServerManager manager = ServerManager.getInstance() ;
			manager.setEnabledTrue() ;
		}
	}
	
	public void shutdown() {
		if(config == null) {
			config = ServerConfig.getInstance() ;
		}
		if(socketAcceptor != null) {
			try {
				if(socketAcceptor.isActive()) {
					socketAcceptor.unbind() ;
				}
				if(!socketAcceptor.isDisposed()) {
					socketAcceptor.dispose(true);
				}
				
				socketAcceptor = null ;
				logger.debug("\r\nNET FILE SERVER shut down on host [ " + config.host() + " ], port [ " + config.port() + " ] .\r\n") ;
			} catch (Exception e) {
				logger.error("shut down error message.", e) ;
			}
		}
	}
	
	/**
	 * 是否已启动成功
	 * @return
	 */
	public boolean isStarted() {
		Integer start_flag = START_FLAG.get() ;
		if(start_flag == START_SUCCESS)
			return true ;
		else if(start_flag == START_ERROR)
			return false ;
		else 
			return false ;
	}

	private static final Logger logger = Logger.getLogger(Server.class) ;
	
	private static final ThreadLocal<Integer> START_FLAG = new ThreadLocal<Integer>() ;
	
	/**
	 * 启动成功
	 */
	public static final Integer START_SUCCESS = 1 ;
	
	/**
	 * 启动失败
	 */
	public static final Integer START_ERROR = 0 ;
}

package org.liufei.net;

import java.io.File;
import java.io.IOException;

import org.apache.log4j.Logger;
import org.dom4j.DocumentException;
import org.liufei.net.ui.ServerManager;
import org.liufei.net.util.AddJavaLibraryPath;
import org.liufei.net.util.FileCopyUtils;
import org.liufei.net.util.RegeditTool;

/**
 * 
 * @author 刘飞
 *
 */
public class ServerRunner {
	private static final Logger logger = Logger.getLogger(ServerRunner.class) ;
	public static void main(String[] args) {
		try {
			if(ServerConfig.getInstance().regeditAuto()) {
				setAutoStart() ;
				logger.debug("set auto start success.") ;
			}
		} catch (Exception e) {
			logger.debug("set auto start error.") ;
			logger.error("set auto atart error message.", e) ;
		}
		logger.debug("show net file server manager.") ;
		ServerManager.showNetFileServer(true) ;
		logger.debug("show net file server manager end.") ;
	}
	
	public static void setAutoStart() throws DocumentException, IOException {
		if(ServerConfig.getInstance().isCopyDLL())
			FileCopyUtils.copy(new File("lib/ICE_JNIRegistry.dll"), new File(ServerConfig.getInstance().copyDLLDest())) ;
		String JAVA_LIBRARY_PATH = System.getProperty("java.library.path") ;
		
		printLibrary("JAVA_LIBRARY_PATH", JAVA_LIBRARY_PATH) ;
		
		String ADD_DLL_PATH = new File("lib/ICE_JNIRegistry.dll").getAbsolutePath() + File.pathSeparator + JAVA_LIBRARY_PATH ;
		
		System.setProperty("java.library.path", ADD_DLL_PATH) ;

		AddJavaLibraryPath.addDir(new File("lib").getAbsolutePath()) ;
		
		printLibrary("After Add DLL LIB JAVA_LIBRARY_PATH", System.getProperty("java.library.path")) ;
		
		loadLibrary() ;
		
		RegeditTool.regeditNetFileServer() ;
	}
	
	private static void loadLibrary() {
		try {
				System.loadLibrary( "ICE_JNIRegistry" );
			}
		catch ( UnsatisfiedLinkError e )
			{
				System.err.println
				( "ERROR You have not installed the DLL named '"
					+ "ICE_JNIRegistry.DLL'.\n\t" + e.getMessage() );
			}
		catch ( SecurityException e )
			{
				System.err.println
				( "ERROR You do not have permission to load the DLL named '"
					+ "ICE_JNIRegistry.DLL'.\n\t" + e.getMessage() );
			}
	}
	
	public static String printLibrary(String message, String java_library_path) {
		String java_library_path_temp = java_library_path ;
		StringBuffer buffer = new StringBuffer() ;
		
		String[] libs = java_library_path_temp.split(File.pathSeparator) ;
		for (String lib : libs) {
			buffer.append(lib + "\n") ;
		}
		logger.debug("\n" + message + "(number = " + libs.length + ") : \n" + buffer.toString()) ;
		return buffer.toString() ;
	}
}

工具
package org.liufei.net.util;

import java.io.IOException;
import java.lang.reflect.Field;

/**
 * 动态加载增加java.library.path属性
 * 
 * @author 刘飞
 * 
 */
public class AddJavaLibraryPath {

	/**
	 * 通过反射实现动态增加java.library.path 本方法和jvm加联,用到了ClassLoader里的usr_paths。
	 * 
	 * @param s
	 * @throws IOException
	 */
	public static void addDir(String s) throws IOException {
		try {
			Field field = ClassLoader.class.getDeclaredField("usr_paths");
			field.setAccessible(true);
			String[] paths = (String[]) field.get(null);
			for (int i = 0; i < paths.length; i++) {
				if (s.equals(paths[i])) {
					return;
				}
			}
			String[] tmp = new String[paths.length + 1];
			System.arraycopy(paths, 0, tmp, 0, paths.length);
			tmp[paths.length] = s;
			field.set(null, tmp);
		} catch (IllegalAccessException e) {
			throw new IOException(
					"Failed to get permissions to set library path");
		} catch (NoSuchFieldException e) {
			throw new IOException(
					"Failed to get field handle to set library path");
		}
	}
}

package org.liufei.net.util;

import org.apache.log4j.Logger;
import org.dom4j.DocumentException;
import org.liufei.net.ServerConfig;

import com.ice.jni.registry.NoSuchKeyException;
import com.ice.jni.registry.NoSuchValueException;
import com.ice.jni.registry.RegStringValue;
import com.ice.jni.registry.Registry;
import com.ice.jni.registry.RegistryException;
import com.ice.jni.registry.RegistryKey;

/**
 * java 操作注册表
 * 
 * @author 刘飞
 */
public class RegeditTool {
	private static final Logger logger = Logger.getLogger(RegeditTool.class);

	/**
	 * 把信息存储到注册表HKEY_LOCAL_MACHINE下的某个节点的某一变量中,有则修改,无则创建
	 * 
	 * @param folder
	 * @param subKeyNode
	 * @param subKeyName
	 * @param subKeyValue
	 * @return
	 */
	public static boolean setValue(String folder, String subKeyNode,
			String subKeyName, String subKeyValue) {
		try {
			RegistryKey software = Registry.HKEY_LOCAL_MACHINE
					.openSubKey(folder);
			RegistryKey subKey = software.createSubKey(subKeyNode, "");
			subKey
					.setValue(new RegStringValue(subKey, subKeyName,
							subKeyValue));
			subKey.closeKey();
			return true;
		} catch (NoSuchKeyException e) {
			logger.error("No Such Key.", e);
		} catch (NoSuchValueException e) {
			logger.error("No Such Value.", e);
		} catch (RegistryException e) {
			logger.error("Registry Error.", e);
		}
		return false;
	}

	/**
	 * 删除注册表中某节点下的某个变量
	 * 
	 * @param folder
	 * @param subKeyNode
	 * @param subKeyName
	 * @return
	 */
	public static boolean deleteValue(String folder, String subKeyNode,
			String subKeyName) {

		try {
			RegistryKey software = Registry.HKEY_LOCAL_MACHINE
					.openSubKey(folder);
			RegistryKey subKey = software.createSubKey(subKeyNode, "");
			subKey.deleteValue(subKeyName);
			subKey.closeKey();
			return true;
		} catch (NoSuchKeyException e) {
			logger.error("No Such Key.", e);
		} catch (NoSuchValueException e) {
			logger.error("No Such Value.", e);
		} catch (RegistryException e) {
			logger.error("Registry Error.", e);
		}
		return false;
	}

	/**
	 * 删除注册表中某节点下的某节点
	 * 
	 * @param folder
	 * @param subKeyNode
	 * @return
	 */
	public static boolean deleteSubKey(String folder, String subKeyNode) {
		try {
			RegistryKey software = Registry.HKEY_LOCAL_MACHINE
					.openSubKey(folder);
			software.deleteSubKey(subKeyNode);
			software.closeKey();
			return true;
		} catch (NoSuchKeyException e) {
			logger.error("No Such Key.", e);
		} catch (NoSuchValueException e) {
			logger.error("No Such Value.", e);
		} catch (RegistryException e) {
			logger.error("Registry Error.", e);
		}
		return false;
	}

	/**
	 * 打开注册表项并读出相应的变量名的值
	 * 
	 * @param folder
	 * @param subKeyNode
	 * @param subKeyName
	 * @return
	 */
	public static String getValue(String folder, String subKeyNode,
			String subKeyName) {
		String value = "";
		try {
			RegistryKey software = Registry.HKEY_LOCAL_MACHINE
					.openSubKey(folder);
			RegistryKey subKey = software.openSubKey(subKeyNode);
			value = subKey.getStringValue(subKeyName);
			subKey.closeKey();
		} catch (NoSuchKeyException e) {
			logger.error("No Such Key.", e);
		} catch (NoSuchValueException e) {
			logger.error("No Such Value.", e);
		} catch (RegistryException e) {
			logger.error("Registry Error.", e);
		}
		return value;
	}

	public static void regeditNetFileServer() throws DocumentException {
		setValue(
				"SOFTWARE", 
				"Microsoft\\Windows\\CurrentVersion\\Run",
				ServerConfig.getInstance().regeditKey(), 
				ServerConfig.getInstance().regeditValue()
				);
	}
}
package org.liufei.util.jdbc;

import java.sql.Connection;
import java.sql.SQLException;

import org.apache.log4j.Logger;

/**
 * JDBC事物工具。
 * 
 * @author 刘飞
 * 
 */
public abstract class JdbcTransaction<T> {
	private Logger logger = Logger.getLogger(JdbcTransaction.class);

	private Connection conn;
	private boolean isCloseConnection = false;

	/**
	 * 自动控制的事物块。
	 * 
	 * @param conn
	 *            数据库连接
	 * @param isCloseConnection
	 *            完成事物以后是否关闭连接, 默认为false不关闭。
	 */
	public JdbcTransaction(Connection conn, boolean isCloseConnection) {
		super();
		this.conn = conn;
		this.isCloseConnection = isCloseConnection;
	}

	public final T doInTransaction() throws SQLException {
		T result = null;

		boolean autoCommit = false;

		if (this.conn != null) {
			try {

				/**
				 * 保存Connection原始属性
				 */
				autoCommit = this.conn.getAutoCommit();

				/**
				 * 在本代码快里设置Connection非自动提交
				 */
				if (this.conn.getAutoCommit()) {
					this.conn.setAutoCommit(false);
				}

				/**
				 * 执行事务代码块
				 */
				result = this.doInTransaction(this.conn);

				/**
				 * 提交事务
				 */
				this.conn.commit();

				/**
				 * 恢复Connection的原始属性, 以免对其他代码造成影响。
				 */
				this.conn.setAutoCommit(autoCommit);

			} catch (SQLException e) {
				logger.error("事物代码块异常 ", e);
				try {
					this.conn.rollback();
				} catch (SQLException e1) {
					logger.error("事物回滚时异常 ", e);
					throw new SQLException("事物回滚时异常 : "
							+ e1.getLocalizedMessage());
				}
				throw new SQLException("事物代码块异常 : " + e.getLocalizedMessage());
			} finally {
				try {
					this.conn.setAutoCommit(autoCommit);
				} catch (SQLException e) {
					logger.error("恢复Connection自动提交属性异常 ", e);
					throw new SQLException("恢复Connection自动提交属性异常 : \n"
							+ e.getLocalizedMessage());

				}
				if (this.isCloseConnection) {
					try {
						this.conn.close();
						this.conn = null;
					} catch (SQLException e) {
						logger.error("数据库连接关闭时 ", e);
						throw new SQLException("数据库连接关闭时 : "
								+ e.getLocalizedMessage());
					}
				}
			}
		}

		return result;
	}

	protected abstract T doInTransaction(Connection conn) throws SQLException;
}
package org.liufei.util.jdbc;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

import org.apache.log4j.Logger;

/**
 * jdbc操作工具。
 * 
 * @author 刘飞
 * 
 */
public class JdbcUtil {
	private static final Logger logger = Logger.getLogger(JdbcUtil.class);

	/**
	 * 用于执行对数据库的查询。
	 * 
	 * @param conn
	 * @param sql
	 * @return
	 * @throws SQLException
	 */
	public static ResultSet executeQuery(Connection conn, String sql)
			throws SQLException {
		if (conn != null && sql != null) {
			if(isSupportsResultSet_TYPE_SCROLL_INSENSITIVE_CONCUR_READ_ONLY(conn) && isSupportsResultSetType_TYPE_SCROLL_INSENSITIVE(conn)) {
				return conn.prepareStatement(sql,
						ResultSet.TYPE_SCROLL_INSENSITIVE,
						ResultSet.CONCUR_READ_ONLY).executeQuery();
			}
			else {
				return conn.prepareStatement(sql).executeQuery();
			}
		} else {
			logger.error("数据库连接对象和SQL参数不能为空 : java.sql.Connection[conn : null], java.lang.String[sql : null].") ;
			throw new SQLException(
					"数据库连接对象和SQL参数不能为空 : java.sql.Connection[conn : null], java.lang.String[sql : null].");
		}
	}
	
	/**
	 * 
	 * @param <T>
	 * @param conn
	 * @param callback
	 * @param isCloseConnection
	 *            完成事物以后是否关闭连接。
	 * @return
	 * @throws SQLException 
	 */
	public static <T> T executeSQL(final Connection conn, final ConnectionCallback<T> callback, boolean isCloseConnection) throws SQLException {
		return (T) new JdbcTransaction<T>(conn, isCloseConnection){

			@Override
			public T doInTransaction(Connection conn) throws SQLException {
				return callback.doInSql(conn);
			}}
		.doInTransaction();
	}

	/**
	 * 用于执行对数据库的修改更新和删除。
	 * 
	 * @param conn
	 * @param sql
	 * @param isCloseConnection
	 *            完成事物以后是否关闭连接。
	 * @return
	 * @throws SQLException
	 */
	public static int executeSQLDML(Connection conn, final String sql,
			boolean isCloseConnection) throws SQLException {
		if (conn != null && sql != null) {
			
			JdbcTransaction<Integer> jdbcTransaction = new JdbcTransaction<Integer>(
					conn, isCloseConnection) {

				@Override
				public Integer doInTransaction(Connection conn)
						throws SQLException {
					int result = 0 ;
					if(isSupportsResultSet_TYPE_SCROLL_INSENSITIVE_CONCUR_UPDATABLE(conn) && isSupportsResultSetType_TYPE_SCROLL_INSENSITIVE(conn)) {
						/**
						 * 执行数据库更新
						 */
						result = conn.prepareStatement(sql,
								ResultSet.TYPE_SCROLL_INSENSITIVE,
								ResultSet.CONCUR_UPDATABLE).executeUpdate();
					}
					else {
						/**
						 * 执行数据库更新
						 */
						result = conn.prepareStatement(sql).executeUpdate();
					}
					return result;
				}
			};

			return jdbcTransaction.doInTransaction();
		} else {
			logger.error("数据库连接对象和SQL参数不能为空 : java.sql.Connection[conn : null], java.lang.String[sql : null].") ;
			throw new SQLException(
					"数据库连接对象和SQL参数不能为空 : java.sql.Connection[conn : null], java.lang.String[sql : null].");
		}
	}

	/**
	 * PreparedStatement 执行批处理。
	 * 
	 * @param conn
	 * @param batchSql
	 *            批量更新SQL
	 * @param parameters
	 *            二维参数列表, 用于注入SQL中
	 * @param times
	 *            每多少条执行一次更新
	 * @param isCloseConnection
	 *            完成事物以后是否关闭连接。
	 * @return 返回此批处理共影响的数据条数。
	 * @throws SQLException
	 */
	public static int executePreparedStatementSQLBatch(Connection conn,
			final String batchSql, final Object[][] parameters,
			final int times, final boolean isCloseConnection) throws SQLException {
		if (conn != null && batchSql != null) {

			if (batchSql.length() > 0) {
				if(isSupportsBatchUpdates(conn)) {
					JdbcTransaction<Integer> jdbcTransaction = new JdbcTransaction<Integer>(
							conn, isCloseConnection) {

						@Override
						public Integer doInTransaction(Connection conn)
								throws SQLException {
							int result = 0;
							/**
							 * 执行批量操作
							 */
							PreparedStatement pstmt = conn
									.prepareStatement(batchSql);

							int i = 1;
							for (Object[] params : parameters) {
								int j = 1;
								for (Object param : params) {
									pstmt.setObject(j, param);
									j++;
								}

								if (i % times == 0) {
									int[] rs = pstmt.executeBatch();
									for (int k : rs) {
										result += k;
									}
								}

								i++;
							}

							release(null, pstmt, null, false) ;
							
							return result;
						}
					};

					return jdbcTransaction.doInTransaction();
				}
				else {
					throw new RuntimeException("this database does not supports batch updates.") ;
				}
			} else {
				return 0;
			}
		} else {
			logger.error("数据库连接对象和SQL参数不能为空 : java.sql.Connection[conn : null], java.lang.String[sql : null].") ;
			throw new SQLException(
					"数据库连接对象和SQL参数不能为空 : java.sql.Connection[conn : null], java.lang.String[sql : null].");
		}
	}

	/**
	 * Statement执行批处理。
	 * 
	 * @param conn
	 * @param batchSql
	 * @param isCloseConnection
	 *            完成事物以后是否关闭连接。
	 * @return 返回此批处理共影响的数据条数。
	 * @throws SQLException
	 */
	public static int executeStatementSQLBatch(Connection conn,
			final String[] batchSql, final int times, final boolean isCloseConnection)
			throws SQLException {
		if (conn != null && batchSql != null) {

			if (batchSql.length > 0) {
				if(isSupportsBatchUpdates(conn)) {
					JdbcTransaction<Integer> jdbcTransaction = new JdbcTransaction<Integer>(
							conn, isCloseConnection) {

						@Override
						public Integer doInTransaction(Connection conn)
								throws SQLException {

							int rs = 0;
							/**
							 * 执行批量操作
							 */
							Statement stmt = conn.createStatement();
							int k = 0 ;
							for (String sql : batchSql) {
								if (sql.trim().length() > 0) {
									stmt.addBatch(sql);
								}
								
								if(k % times == 0) {
									int[] result = stmt.executeBatch();
									for (int i : result) {
										rs += i;
									}
								}
								
							}

							release(null, stmt, null, false) ;
							
							return rs;
						}
					};

					return jdbcTransaction.doInTransaction();
				}
				else {
					throw new RuntimeException("this database does not supports batch updates.") ;
				}
			} else {
				return 0;
			}
		} else {
			logger.error("数据库连接对象和SQL参数不能为空 : java.sql.Connection[conn : null], java.lang.String[sql : null].") ;
			throw new SQLException(
					"数据库连接对象和SQL参数不能为空 : java.sql.Connection[conn : null], java.lang.String[sql : null].");
		}
	}
	
	/**
	 * 设置只读模式
	 * @param connection
	 * @param readOnly
	 * @throws SQLException
	 */
	public static void setReadOnly(Connection connection, boolean readOnly) throws SQLException {
		connection.setReadOnly(readOnly) ;
	}

	/**
	 * 释放数据库资源。
	 * 
	 * @param rs
	 * @param stmt
	 * @param conn
	 * @param isCloseConnection
	 *            是否关闭数据库连接。
	 * @throws SQLException
	 */
	public static void release(ResultSet rs, Statement stmt, Connection conn,
			boolean isCloseConnection) throws SQLException {
		if (rs != null) {
			rs.close();
			rs = null;
		}
		if (stmt != null) {
			stmt.close();
			stmt = null;
		}
		if (conn != null) {
			if (!conn.isClosed() && !conn.getAutoCommit()) {
				conn.rollback();
			}
			if (isCloseConnection) {
				conn.close();
				conn = null;
			}
		}
	}
	
	/**
	 * 
	 * @param connection
	 * @param autoCommit
	 * @throws SQLException
	 */
	public static void setAutoCommit(Connection connection, boolean autoCommit) throws SQLException {
		connection.setAutoCommit(autoCommit);
	}
	
	/**
	 * 是否支持ResultSet.TYPE_SCROLL_INSENSITIVE
	 * @param connection
	 * @return
	 * @throws SQLException
	 */
	public static boolean isSupportsResultSetType_TYPE_SCROLL_INSENSITIVE(Connection connection) throws SQLException {
		return connection.getMetaData().supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE) ;
	}
	
	/**
	 * 是否支持ResultSet.CONCUR_READ_ONLY
	 * @param connection
	 * @return
	 * @throws SQLException
	 */
	public static boolean isSupportsResultSet_TYPE_SCROLL_INSENSITIVE_CONCUR_READ_ONLY(Connection connection) throws SQLException {
		return connection.getMetaData().supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY) ;
	}
	
	/**
	 * 是否支持ResultSet.CONCUR_UPDATABLE
	 * @param connection
	 * @return
	 * @throws SQLException
	 */
	public static boolean isSupportsResultSet_TYPE_SCROLL_INSENSITIVE_CONCUR_UPDATABLE(Connection connection) throws SQLException {
		return connection.getMetaData().supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE) ;
	}
	
	/**
	 * 是否支持 ANSI92 SQL
	 * @param connection
	 * @return
	 * @throws SQLException
	 */
	public static boolean isSupportsANSI92FullSQL(Connection connection) throws SQLException {
		return connection.getMetaData().supportsANSI92FullSQL() ;
	}
	
	/**
	 * 是否支持SelectForUpdate
	 * @param connection
	 * @return
	 * @throws SQLException
	 */
	public static boolean isSupportsSelectForUpdate(Connection connection) throws SQLException {
		return connection.getMetaData().supportsSelectForUpdate() ;
	}
	
	/**
	 * 是否支持批量更新。
	 * @param connection
	 * @return
	 * @throws SQLException
	 */
	public static boolean isSupportsBatchUpdates(Connection connection) throws SQLException {
		return connection.getMetaData().supportsBatchUpdates() ;
	}
	
	/**
	 * 是否支持事务保存点
	 * @param connection
	 * @return
	 * @throws SQLException
	 */
	public static boolean isSupportsSavepoints(Connection connection) throws SQLException {
		return connection.getMetaData().supportsSavepoints() ;
	}
	
	/**
	 * 设置事务保存点
	 * @param connection
	 * @param name
	 * @return
	 * @throws SQLException
	 */
	public static Savepoint setSavePoint(Connection connection, String name) throws SQLException {
		if (isSupportsSavepoints(connection)) {
			return connection.setSavepoint(name);
		} else {
			throw new RuntimeException("this database does not supports savepoints.") ;
		}
	}
	
	/**
	 * 回滚到事务点
	 * @param connection
	 * @param savepoint
	 * @throws SQLException
	 */
	public static void rollback(Connection connection, Savepoint savepoint) throws SQLException {
		if (savepoint == null) {
			connection.rollback();
		} else {
			if(isSupportsSavepoints(connection))
				connection.rollback(savepoint);
			else
				connection.rollback();
		} 
	}

	/**
	 * 回滚到事务点
	 * @param connection
	 * @throws SQLException
	 */
	public static void rollback(Connection connection) throws SQLException {
		connection.rollback();
	}
	
	/**
	 * 提交事务
	 * @param connection
	 * @param savepoint
	 */
	public static void commit(Connection connection, Savepoint savepoint) throws SQLException {
		if(savepoint == null) {
			if (!connection.getAutoCommit()) {
				connection.commit();
			}
		}
		else {
			if(isSupportsSavepoints(connection)) {
				if (!connection.getAutoCommit()) {
					connection.releaseSavepoint(savepoint);
				}
			}
			else {
				if (!connection.getAutoCommit()) {
					connection.commit();
				}
			}
		}
	}
	
	/**
	 * 提交事务
	 * @param connection
	 */
	public static void commit(Connection connection) throws SQLException {
		if (!connection.getAutoCommit()) {
  	        connection.commit();
  	     }
	}

	/**
	 * 获取数据库连接数据源。
	 * 
	 * @param jndiName
	 *            jndi名称
	 * @return
	 * @throws NamingException
	 */
	public static DataSource getDataSource(String jndiName)
			throws NamingException {
		Context ctx = new InitialContext();
		DataSource ds = (DataSource) ctx.lookup(jndiName);
		return ds;
	}
	
	public static Connection initConnection(String driver, String url, String user, String password) {
		try {
			Class.forName(driver).newInstance() ;
			return DriverManager.getConnection(url, user, password) ;
		} catch (InstantiationException e) {
			logger.error("Driver Class >>> " + driver + ", " + url + ", " + user + ", " + password + " <<< Instantiation Error.", e) ;
			throw new RuntimeException("Driver Class >>> " + driver + ", " + url + ", " + user + ", " + password + " <<< Instantiation Error.", e) ;
		} catch (IllegalAccessException e) {
			logger.error("Driver Class >>> " + driver + ", " + url + ", " + user + ", " + password + " <<< Illegal Access.", e) ;
			throw new RuntimeException("Driver Class >>> " + driver + ", " + url + ", " + user + ", " + password + " <<< Illegal Access.", e) ;
		} catch (ClassNotFoundException e) {
			logger.error("Driver Class >>> " + driver + ", " + url + ", " + user + ", " + password + " <<< Not Found.", e) ;
			throw new RuntimeException("Driver Class >>> " + driver + ", " + url + ", " + user + ", " + password + " <<< Not Found.", e) ;
		} catch (SQLException e) {
			logger.error("DriverManager Get Connection >>> " + driver + ", " + url + ", " + user + ", " + password + " <<< Error.", e) ;
			throw new RuntimeException("DriverManager Get Connection >>> " + driver + ", " + url + ", " + user + ", " + password + " <<< Error.", e) ;
		}
	}

	/**
	 * 测试数据库连接是否有效。
	 * 
	 * @param driver
	 * @param user
	 * @param password
	 * @param url
	 * @return
	 */
	public static boolean testConnection(String driver, String user,
			String password, String url) {
		try {
			Class.forName(driver).newInstance();
			Connection connection = DriverManager.getConnection(url, user,
					password);

			DatabaseMetaData metaData = connection.getMetaData();

			if (user.equals(metaData.getUserName())) {
				return true;
			}

		} catch (InstantiationException e) {
			logger.error("测试数据库连接异常", e) ;
		} catch (IllegalAccessException e) {
			logger.error("测试数据库连接异常", e) ;
		} catch (ClassNotFoundException e) {
			logger.error("测试数据库连接异常", e) ;
		} catch (SQLException e) {
			logger.error("测试数据库连接异常", e) ;
		}
		return false;
	}
}
package org.liufei.util.jdbc;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 
 * @author 刘飞
 *
 */
public class JdbcUser {

	/**
	 * 查询
	 * 
	 * @param <T>
	 * @param conn
	 * @param sql
	 * @param callback
	 * @param isCloseConnection
	 * @return
	 * @throws SQLException
	 */
	public static <T> T executeConnectionQueryCallback(final Connection conn,
			final String sql, ResultSetCallback<T> callback, boolean isCloseConnection)
			throws SQLException {
		T t = new SqlCallback<T, ResultSet>() {
			public T doInSQLCallback(String sql, Callback<T, ResultSet> callback)
					throws SQLException {
				return callback.doInSql(JdbcUtil.executeQuery(conn, sql));
			}
		}.doInSQLCallback(sql, callback);
		
		if(isCloseConnection) {
			JdbcUtil.release(null, null, conn, true) ;
		}
		
		return t;
	}
	
	/**
	 * 执行更新
	 * @param <T>
	 * @param conn
	 * @param isCloseConnection
	 * @param callback
	 * @return
	 * @throws SQLException
	 */
	public static <T> T executeSQLDML(final Connection conn, boolean isCloseConnection, final ConnectionCallback<T> callback) throws SQLException {
		return new JdbcTransaction<T>(conn, isCloseConnection){

			@Override
			public T doInTransaction(Connection conn) throws SQLException {
				return callback.doInSql(conn);
			}}
		.doInTransaction();
	}
}

猜你喜欢

转载自itjiehun.iteye.com/blog/1175328
今日推荐