limd
4 years ago
18 changed files with 1867 additions and 0 deletions
-
120other/java/hdfs-over-ftp/pom.xml
-
14other/java/hdfs-over-ftp/src/main/java/org/apache/hadoop/seaweed/ftp/ApplicationServer.java
-
27other/java/hdfs-over-ftp/src/main/java/org/apache/hadoop/seaweed/ftp/config/SwaggerConfig.java
-
71other/java/hdfs-over-ftp/src/main/java/org/apache/hadoop/seaweed/ftp/controller/FtpManagerController.java
-
98other/java/hdfs-over-ftp/src/main/java/org/apache/hadoop/seaweed/ftp/controller/UserController.java
-
71other/java/hdfs-over-ftp/src/main/java/org/apache/hadoop/seaweed/ftp/controller/vo/FtpUser.java
-
43other/java/hdfs-over-ftp/src/main/java/org/apache/hadoop/seaweed/ftp/controller/vo/Result.java
-
102other/java/hdfs-over-ftp/src/main/java/org/apache/hadoop/seaweed/ftp/service/HFtpService.java
-
333other/java/hdfs-over-ftp/src/main/java/org/apache/hadoop/seaweed/ftp/service/filesystem/HdfsFileObject.java
-
14other/java/hdfs-over-ftp/src/main/java/org/apache/hadoop/seaweed/ftp/service/filesystem/HdfsFileSystemManager.java
-
104other/java/hdfs-over-ftp/src/main/java/org/apache/hadoop/seaweed/ftp/service/filesystem/HdfsFileSystemView.java
-
72other/java/hdfs-over-ftp/src/main/java/org/apache/hadoop/seaweed/ftp/service/filesystem/HdfsOverFtpSystem.java
-
239other/java/hdfs-over-ftp/src/main/java/org/apache/hadoop/seaweed/ftp/users/HdfsUser.java
-
453other/java/hdfs-over-ftp/src/main/java/org/apache/hadoop/seaweed/ftp/users/HdfsUserManager.java
-
15other/java/hdfs-over-ftp/src/main/resources/application.yml
-
39other/java/hdfs-over-ftp/src/main/resources/assembly.xml
-
40other/java/hdfs-over-ftp/src/main/resources/logback-spring.xml
-
12other/java/hdfs-over-ftp/users.properties
@ -0,0 +1,120 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
|
<modelVersion>4.0.0</modelVersion> |
||||
|
|
||||
|
<groupId>hdfs-over-ftp</groupId> |
||||
|
<artifactId>hdfs-over-ftp</artifactId> |
||||
|
<version>1.0</version> |
||||
|
|
||||
|
<parent> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-parent</artifactId> |
||||
|
<version>2.4.3</version> |
||||
|
</parent> |
||||
|
|
||||
|
<dependencies> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-web</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>io.springfox</groupId> |
||||
|
<artifactId>springfox-swagger2</artifactId> |
||||
|
<version>2.9.2</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>io.springfox</groupId> |
||||
|
<artifactId>springfox-swagger-ui</artifactId> |
||||
|
<version>2.9.2</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.apache.hadoop</groupId> |
||||
|
<artifactId>hadoop-common</artifactId> |
||||
|
<version>3.2.1</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.apache.hadoop</groupId> |
||||
|
<artifactId>hadoop-client</artifactId> |
||||
|
<version>3.2.1</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.apache.ftpserver</groupId> |
||||
|
<artifactId>ftpserver-core</artifactId> |
||||
|
<version>1.1.1</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>com.github.chrislusf</groupId> |
||||
|
<artifactId>seaweedfs-hadoop3-client</artifactId> |
||||
|
<version>1.6.2</version> |
||||
|
</dependency> |
||||
|
</dependencies> |
||||
|
|
||||
|
|
||||
|
<build> |
||||
|
<plugins> |
||||
|
<plugin> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-maven-plugin</artifactId> |
||||
|
</plugin> |
||||
|
|
||||
|
<plugin> |
||||
|
<groupId>org.apache.maven.plugins</groupId> |
||||
|
<artifactId>maven-compiler-plugin</artifactId> |
||||
|
<version>3.1</version> |
||||
|
<configuration> |
||||
|
<source>1.8</source> |
||||
|
<target>1.8</target> |
||||
|
<encoding>UTF-8</encoding> |
||||
|
<compilerArguments> |
||||
|
<verbose /> |
||||
|
<bootclasspath>${java.home}/lib/rt.jar</bootclasspath> |
||||
|
</compilerArguments> |
||||
|
</configuration> |
||||
|
</plugin> |
||||
|
|
||||
|
<plugin> |
||||
|
<groupId>org.apache.maven.plugins</groupId> |
||||
|
<artifactId>maven-jar-plugin</artifactId> |
||||
|
<version>2.6</version> |
||||
|
<configuration> |
||||
|
<archive> |
||||
|
<manifest> |
||||
|
<mainClass>org.apache.hadoop.seaweed.ftp.ApplicationServer</mainClass> |
||||
|
<addClasspath>true</addClasspath> |
||||
|
<classpathPrefix>lib/</classpathPrefix> |
||||
|
</manifest> |
||||
|
<manifestEntries> |
||||
|
<Class-Path>./</Class-Path> |
||||
|
</manifestEntries> |
||||
|
</archive> |
||||
|
</configuration> |
||||
|
</plugin> |
||||
|
|
||||
|
<plugin> |
||||
|
<artifactId>maven-assembly-plugin</artifactId> |
||||
|
<configuration> |
||||
|
<appendAssemblyId>false</appendAssemblyId> |
||||
|
<descriptors> |
||||
|
<descriptor>src/main/resources/assembly.xml</descriptor> |
||||
|
</descriptors> |
||||
|
</configuration> |
||||
|
<executions> |
||||
|
<execution> |
||||
|
<id>make-assembly</id> |
||||
|
<phase>package</phase> |
||||
|
<goals> |
||||
|
<goal>single</goal> |
||||
|
</goals> |
||||
|
</execution> |
||||
|
</executions> |
||||
|
</plugin> |
||||
|
</plugins> |
||||
|
</build> |
||||
|
|
||||
|
</project> |
@ -0,0 +1,14 @@ |
|||||
|
package org.apache.hadoop.seaweed.ftp; |
||||
|
|
||||
|
import org.springframework.boot.SpringApplication; |
||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
|
|
||||
|
|
||||
|
@SpringBootApplication |
||||
|
public class ApplicationServer { |
||||
|
|
||||
|
public static void main(String[] args) { |
||||
|
SpringApplication.run(ApplicationServer.class, args); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,27 @@ |
|||||
|
package org.apache.hadoop.seaweed.ftp.config; |
||||
|
|
||||
|
import org.springframework.context.annotation.Bean; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
import springfox.documentation.builders.ApiInfoBuilder; |
||||
|
import springfox.documentation.builders.PathSelectors; |
||||
|
import springfox.documentation.builders.RequestHandlerSelectors; |
||||
|
import springfox.documentation.spi.DocumentationType; |
||||
|
import springfox.documentation.spring.web.plugins.Docket; |
||||
|
import springfox.documentation.swagger2.annotations.EnableSwagger2; |
||||
|
|
||||
|
@Configuration |
||||
|
@EnableSwagger2 |
||||
|
public class SwaggerConfig { |
||||
|
@Bean |
||||
|
public Docket createRestApi() { |
||||
|
return new Docket(DocumentationType.SWAGGER_2) |
||||
|
.pathMapping("/") |
||||
|
.select() |
||||
|
.apis(RequestHandlerSelectors.basePackage("org.apache.hadoop.seaweed.ftp")) |
||||
|
.paths(PathSelectors.any()) |
||||
|
.build().apiInfo(new ApiInfoBuilder() |
||||
|
.title("FTP API Doc") |
||||
|
.version("1.0") |
||||
|
.build()); |
||||
|
} |
||||
|
} |
@ -0,0 +1,71 @@ |
|||||
|
package org.apache.hadoop.seaweed.ftp.controller; |
||||
|
|
||||
|
import io.swagger.annotations.Api; |
||||
|
import io.swagger.annotations.ApiOperation; |
||||
|
import org.apache.hadoop.seaweed.ftp.service.HFtpService; |
||||
|
import org.apache.hadoop.seaweed.ftp.controller.vo.Result; |
||||
|
import org.apache.log4j.Logger; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||
|
import org.springframework.web.bind.annotation.PutMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
import org.springframework.web.bind.annotation.RestController; |
||||
|
|
||||
|
import java.util.HashMap; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
@RestController |
||||
|
@RequestMapping("/manager") |
||||
|
@Api(tags = "FTP操作管理") |
||||
|
public class FtpManagerController { |
||||
|
|
||||
|
private static Logger log = Logger.getLogger(FtpManagerController.class); |
||||
|
|
||||
|
@Autowired |
||||
|
private HFtpService hdfsOverFtpServer; |
||||
|
|
||||
|
@GetMapping("/status") |
||||
|
@ApiOperation("查看FTP服务状态") |
||||
|
public Result status() { |
||||
|
Map map = new HashMap<>(); |
||||
|
try { |
||||
|
boolean status = hdfsOverFtpServer.statusServer(); |
||||
|
map.put("is_running", status); |
||||
|
return new Result(true, map, "FTP 服务状态获取成功"); |
||||
|
}catch (Exception e) { |
||||
|
log.error(e); |
||||
|
map.put("is_running", false); |
||||
|
return new Result(true, map, "FTP 服务状态获取成功"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@PutMapping("/start") |
||||
|
@ApiOperation("启动FTP服务") |
||||
|
public Result start() { |
||||
|
try { |
||||
|
boolean status = hdfsOverFtpServer.statusServer(); |
||||
|
if(!status) { |
||||
|
hdfsOverFtpServer.startServer(); |
||||
|
} |
||||
|
return new Result(true, "FTP 服务启动成功"); |
||||
|
}catch (Exception e) { |
||||
|
log.error(e); |
||||
|
return new Result(false, "FTP 服务启动失败"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@PutMapping("/stop") |
||||
|
@ApiOperation("停止FTP服务") |
||||
|
public Result stop() { |
||||
|
try { |
||||
|
boolean status = hdfsOverFtpServer.statusServer(); |
||||
|
if(status) { |
||||
|
hdfsOverFtpServer.stopServer(); |
||||
|
} |
||||
|
return new Result(true, "FTP 服务停止成功"); |
||||
|
}catch (Exception e) { |
||||
|
log.error(e); |
||||
|
return new Result(false, "FTP 服务停止失败"); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,98 @@ |
|||||
|
package org.apache.hadoop.seaweed.ftp.controller; |
||||
|
|
||||
|
import io.swagger.annotations.Api; |
||||
|
import io.swagger.annotations.ApiOperation; |
||||
|
import org.apache.ftpserver.ftplet.User; |
||||
|
import org.apache.ftpserver.usermanager.Md5PasswordEncryptor; |
||||
|
import org.apache.ftpserver.usermanager.UserFactory; |
||||
|
import org.apache.hadoop.seaweed.ftp.controller.vo.FtpUser; |
||||
|
import org.apache.hadoop.seaweed.ftp.controller.vo.Result; |
||||
|
import org.apache.hadoop.seaweed.ftp.users.HdfsUserManager; |
||||
|
import org.apache.log4j.Logger; |
||||
|
import org.springframework.web.bind.annotation.*; |
||||
|
|
||||
|
import java.io.File; |
||||
|
|
||||
|
@RestController |
||||
|
@RequestMapping("/user") |
||||
|
@Api(tags = "FTP用户管理") |
||||
|
public class UserController { |
||||
|
|
||||
|
private static Logger log = Logger.getLogger(UserController.class); |
||||
|
|
||||
|
/*** |
||||
|
* { |
||||
|
* "name": "test", |
||||
|
* "password": "test", |
||||
|
* "homeDirectory": "/buckets/test/" |
||||
|
* } |
||||
|
* @param ftpUser |
||||
|
* @return |
||||
|
*/ |
||||
|
@PostMapping("/add") |
||||
|
@ApiOperation("新增/编辑用户") |
||||
|
public Result add(@RequestBody FtpUser ftpUser) { |
||||
|
try { |
||||
|
HdfsUserManager userManagerFactory = new HdfsUserManager(); |
||||
|
userManagerFactory.setFile(new File(System.getProperty("user.dir") + File.separator + "users.properties")); |
||||
|
userManagerFactory.setPasswordEncryptor(new Md5PasswordEncryptor()); |
||||
|
|
||||
|
UserFactory userFactory = new UserFactory(); |
||||
|
userFactory.setHomeDirectory(ftpUser.getHomeDirectory()); |
||||
|
userFactory.setName(ftpUser.getName()); |
||||
|
userFactory.setPassword(ftpUser.getPassword()); |
||||
|
userFactory.setEnabled(ftpUser.isEnabled()); |
||||
|
userFactory.setMaxIdleTime(ftpUser.getMaxIdleTime()); |
||||
|
|
||||
|
User user = userFactory.createUser(); |
||||
|
userManagerFactory.save(user, ftpUser.isRenamePush()); |
||||
|
return new Result(true, "新建用户成功"); |
||||
|
}catch (Exception e) { |
||||
|
log.error(e); |
||||
|
return new Result(false, "新建用户失败"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@DeleteMapping("/delete/{user}") |
||||
|
@ApiOperation("删除用户") |
||||
|
public Result delete(@PathVariable(value = "user") String user) { |
||||
|
try { |
||||
|
HdfsUserManager userManagerFactory = new HdfsUserManager(); |
||||
|
userManagerFactory.setFile(new File(System.getProperty("user.dir") + File.separator + "users.properties")); |
||||
|
userManagerFactory.delete(user); |
||||
|
return new Result(true, "删除用户成功"); |
||||
|
}catch (Exception e) { |
||||
|
log.error(e); |
||||
|
return new Result(false, "删除用户失败"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/show/{userName}") |
||||
|
@ApiOperation("查看用户") |
||||
|
public Result show(@PathVariable(value = "userName") String userName) { |
||||
|
try { |
||||
|
HdfsUserManager userManagerFactory = new HdfsUserManager(); |
||||
|
userManagerFactory.setFile(new File(System.getProperty("user.dir") + File.separator + "users.properties")); |
||||
|
User user = userManagerFactory.getUserByName(userName); |
||||
|
FtpUser ftpUser = new FtpUser(user.getHomeDirectory(), user.getPassword(), user.getEnabled(), user.getName(), user.getMaxIdleTime(), HdfsUserManager.getUserRenamePush(userName)); |
||||
|
return new Result(true, ftpUser, "获取用户信息成功"); |
||||
|
}catch (Exception e) { |
||||
|
log.error(e); |
||||
|
return new Result(false, "获取用户信息失败"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/list") |
||||
|
@ApiOperation("列举用户") |
||||
|
public Result list() { |
||||
|
try { |
||||
|
HdfsUserManager userManagerFactory = new HdfsUserManager(); |
||||
|
userManagerFactory.setFile(new File(System.getProperty("user.dir") + File.separator + "users.properties")); |
||||
|
String[] allUserNames = userManagerFactory.getAllUserNames(); |
||||
|
return new Result(true, allUserNames, "列举用户成功"); |
||||
|
}catch (Exception e) { |
||||
|
log.error(e); |
||||
|
return new Result(false, "列举用户失败"); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,71 @@ |
|||||
|
package org.apache.hadoop.seaweed.ftp.controller.vo; |
||||
|
|
||||
|
public class FtpUser { |
||||
|
|
||||
|
private String homeDirectory; |
||||
|
private String password; |
||||
|
private boolean enabled; |
||||
|
private String name; |
||||
|
private int maxIdleTime; |
||||
|
private boolean renamePush; |
||||
|
|
||||
|
public FtpUser() { |
||||
|
} |
||||
|
|
||||
|
public FtpUser(String homeDirectory, String password, boolean enabled, String name, int maxIdleTime, boolean renamePush) { |
||||
|
this.homeDirectory = homeDirectory; |
||||
|
this.password = password; |
||||
|
this.enabled = enabled; |
||||
|
this.name = name; |
||||
|
this.maxIdleTime = maxIdleTime; |
||||
|
this.renamePush = renamePush; |
||||
|
} |
||||
|
|
||||
|
public String getHomeDirectory() { |
||||
|
return homeDirectory; |
||||
|
} |
||||
|
|
||||
|
public void setHomeDirectory(String homeDirectory) { |
||||
|
this.homeDirectory = homeDirectory; |
||||
|
} |
||||
|
|
||||
|
public String getPassword() { |
||||
|
return password; |
||||
|
} |
||||
|
|
||||
|
public void setPassword(String password) { |
||||
|
this.password = password; |
||||
|
} |
||||
|
|
||||
|
public boolean isEnabled() { |
||||
|
return enabled; |
||||
|
} |
||||
|
|
||||
|
public void setEnabled(boolean enabled) { |
||||
|
this.enabled = enabled; |
||||
|
} |
||||
|
|
||||
|
public String getName() { |
||||
|
return name; |
||||
|
} |
||||
|
|
||||
|
public void setName(String name) { |
||||
|
this.name = name; |
||||
|
} |
||||
|
|
||||
|
public int getMaxIdleTime() { |
||||
|
return maxIdleTime; |
||||
|
} |
||||
|
|
||||
|
public void setMaxIdleTime(int maxIdleTime) { |
||||
|
this.maxIdleTime = maxIdleTime; |
||||
|
} |
||||
|
|
||||
|
public boolean isRenamePush() { |
||||
|
return renamePush; |
||||
|
} |
||||
|
|
||||
|
public void setRenamePush(boolean renamePush) { |
||||
|
this.renamePush = renamePush; |
||||
|
} |
||||
|
} |
@ -0,0 +1,43 @@ |
|||||
|
package org.apache.hadoop.seaweed.ftp.controller.vo; |
||||
|
|
||||
|
public class Result { |
||||
|
|
||||
|
private boolean status; |
||||
|
private Object data; |
||||
|
private String message; |
||||
|
|
||||
|
public Result(boolean status, String message) { |
||||
|
this.status = status; |
||||
|
this.message = message; |
||||
|
} |
||||
|
|
||||
|
public Result(boolean status, Object data, String message) { |
||||
|
this.status = status; |
||||
|
this.message = message; |
||||
|
this.data = data; |
||||
|
} |
||||
|
|
||||
|
public boolean isStatus() { |
||||
|
return status; |
||||
|
} |
||||
|
|
||||
|
public void setStatus(boolean status) { |
||||
|
this.status = status; |
||||
|
} |
||||
|
|
||||
|
public String getMessage() { |
||||
|
return message; |
||||
|
} |
||||
|
|
||||
|
public void setMessage(String message) { |
||||
|
this.message = message; |
||||
|
} |
||||
|
|
||||
|
public Object getData() { |
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
public void setData(Object data) { |
||||
|
this.data = data; |
||||
|
} |
||||
|
} |
@ -0,0 +1,102 @@ |
|||||
|
package org.apache.hadoop.seaweed.ftp.service; |
||||
|
|
||||
|
import org.apache.ftpserver.DataConnectionConfiguration; |
||||
|
import org.apache.ftpserver.DataConnectionConfigurationFactory; |
||||
|
import org.apache.ftpserver.FtpServer; |
||||
|
import org.apache.ftpserver.FtpServerFactory; |
||||
|
import org.apache.ftpserver.command.CommandFactoryFactory; |
||||
|
import org.apache.ftpserver.listener.ListenerFactory; |
||||
|
import org.apache.hadoop.seaweed.ftp.service.filesystem.HdfsFileSystemManager; |
||||
|
import org.apache.hadoop.seaweed.ftp.service.filesystem.HdfsOverFtpSystem; |
||||
|
import org.apache.hadoop.seaweed.ftp.users.HdfsUserManager; |
||||
|
import org.apache.log4j.Logger; |
||||
|
import org.springframework.beans.factory.annotation.Value; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import java.io.File; |
||||
|
|
||||
|
/** |
||||
|
* reference: https://github.com/iponweb/hdfs-over-ftp |
||||
|
*/ |
||||
|
@Component |
||||
|
public class HFtpService { |
||||
|
|
||||
|
private static Logger log = Logger.getLogger(HFtpService.class); |
||||
|
|
||||
|
@Value("${ftp.port}") |
||||
|
private int port = 0; |
||||
|
|
||||
|
@Value("${ftp.passive-address}") |
||||
|
private String passiveAddress; |
||||
|
|
||||
|
@Value("${ftp.passive-ports}") |
||||
|
private String passivePorts; |
||||
|
|
||||
|
@Value("${hdfs.uri}") |
||||
|
private String hdfsUri; |
||||
|
|
||||
|
@Value("${seaweedFs.enable}") |
||||
|
private boolean seaweedFsEnable; |
||||
|
|
||||
|
@Value("${seaweedFs.access}") |
||||
|
private String seaweedFsAccess; |
||||
|
|
||||
|
@Value("${seaweedFs.replication}") |
||||
|
private String seaweedFsReplication; |
||||
|
|
||||
|
private FtpServer ftpServer = null; |
||||
|
|
||||
|
public void startServer() throws Exception { |
||||
|
log.info("Starting HDFS-Over-Ftp server. port: " + port + " passive-address: " + passiveAddress + " passive-ports: " + passivePorts + " hdfs-uri: " + hdfsUri); |
||||
|
|
||||
|
HdfsOverFtpSystem.setHdfsUri(hdfsUri); |
||||
|
HdfsOverFtpSystem.setSeaweedFsEnable(seaweedFsEnable); |
||||
|
HdfsOverFtpSystem.setSeaweedFsAccess(seaweedFsAccess); |
||||
|
HdfsOverFtpSystem.setSeaweedFsReplication(seaweedFsReplication); |
||||
|
|
||||
|
FtpServerFactory server = new FtpServerFactory(); |
||||
|
server.setFileSystem(new HdfsFileSystemManager()); |
||||
|
|
||||
|
ListenerFactory factory = new ListenerFactory(); |
||||
|
factory.setPort(port); |
||||
|
|
||||
|
DataConnectionConfigurationFactory dccFactory = new DataConnectionConfigurationFactory(); |
||||
|
dccFactory.setPassiveAddress("0.0.0.0"); |
||||
|
dccFactory.setPassivePorts(passivePorts); |
||||
|
dccFactory.setPassiveExternalAddress(passiveAddress); |
||||
|
DataConnectionConfiguration dcc = dccFactory.createDataConnectionConfiguration(); |
||||
|
factory.setDataConnectionConfiguration(dcc); |
||||
|
|
||||
|
server.addListener("default", factory.createListener()); |
||||
|
|
||||
|
HdfsUserManager userManager = new HdfsUserManager(); |
||||
|
final File file = loadResource("/users.properties"); |
||||
|
userManager.setFile(file); |
||||
|
server.setUserManager(userManager); |
||||
|
|
||||
|
CommandFactoryFactory cmFact = new CommandFactoryFactory(); |
||||
|
cmFact.setUseDefaultCommands(true); |
||||
|
server.setCommandFactory(cmFact.createCommandFactory()); |
||||
|
|
||||
|
// start the server |
||||
|
ftpServer = server.createServer(); |
||||
|
ftpServer.start(); |
||||
|
} |
||||
|
|
||||
|
public void stopServer() { |
||||
|
log.info("Stopping Hdfs-Over-Ftp server. port: " + port + " passive-address: " + passiveAddress + " passive-ports: " + passivePorts + " hdfs-uri: " + hdfsUri); |
||||
|
ftpServer.stop(); |
||||
|
} |
||||
|
|
||||
|
public boolean statusServer() { |
||||
|
try { |
||||
|
return !ftpServer.isStopped(); |
||||
|
}catch (Exception e) { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static File loadResource(String resourceName) { |
||||
|
return new File(System.getProperty("user.dir") + resourceName); |
||||
|
} |
||||
|
} |
@ -0,0 +1,333 @@ |
|||||
|
package org.apache.hadoop.seaweed.ftp.service.filesystem; |
||||
|
|
||||
|
import org.apache.ftpserver.ftplet.FtpFile; |
||||
|
import org.apache.ftpserver.ftplet.User; |
||||
|
import org.apache.hadoop.fs.*; |
||||
|
import org.apache.hadoop.seaweed.ftp.users.HdfsUser; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
|
||||
|
import java.io.File; |
||||
|
import java.io.IOException; |
||||
|
import java.io.InputStream; |
||||
|
import java.io.OutputStream; |
||||
|
import java.util.Arrays; |
||||
|
import java.util.Collections; |
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* This class implements all actions to HDFS |
||||
|
*/ |
||||
|
public class HdfsFileObject implements FtpFile { |
||||
|
|
||||
|
private final Logger log = LoggerFactory.getLogger(HdfsFileObject.class); |
||||
|
|
||||
|
private Path homePath; |
||||
|
private Path path; |
||||
|
private Path fullPath; |
||||
|
private HdfsUser user; |
||||
|
|
||||
|
/** |
||||
|
* Constructs HdfsFileObject from path |
||||
|
* |
||||
|
* @param path path to represent object |
||||
|
* @param user accessor of the object |
||||
|
*/ |
||||
|
public HdfsFileObject(String homePath, String path, User user) { |
||||
|
this.homePath = new Path(homePath); |
||||
|
this.path = new Path(path); |
||||
|
this.fullPath = new Path(homePath + path); |
||||
|
this.user = (HdfsUser) user; |
||||
|
} |
||||
|
|
||||
|
public String getAbsolutePath() { |
||||
|
// strip the last '/' if necessary |
||||
|
String fullName = path.toString(); |
||||
|
int filelen = fullName.length(); |
||||
|
if ((filelen != 1) && (fullName.charAt(filelen - 1) == '/')) { |
||||
|
fullName = fullName.substring(0, filelen - 1); |
||||
|
} |
||||
|
|
||||
|
return fullName; |
||||
|
} |
||||
|
|
||||
|
public String getName() { |
||||
|
return path.getName(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* HDFS has no hidden objects |
||||
|
* |
||||
|
* @return always false |
||||
|
*/ |
||||
|
public boolean isHidden() { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Checks if the object is a directory |
||||
|
* |
||||
|
* @return true if the object is a directory |
||||
|
*/ |
||||
|
public boolean isDirectory() { |
||||
|
try { |
||||
|
log.debug("is directory? : " + fullPath); |
||||
|
FileSystem dfs = HdfsOverFtpSystem.getDfs(); |
||||
|
FileStatus fs = dfs.getFileStatus(fullPath); |
||||
|
return fs.isDir(); |
||||
|
} catch (IOException e) { |
||||
|
log.debug(fullPath + " is not dir", e); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Checks if the object is a file |
||||
|
* |
||||
|
* @return true if the object is a file |
||||
|
*/ |
||||
|
public boolean isFile() { |
||||
|
try { |
||||
|
FileSystem dfs = HdfsOverFtpSystem.getDfs(); |
||||
|
return dfs.isFile(fullPath); |
||||
|
} catch (IOException e) { |
||||
|
log.debug(fullPath + " is not file", e); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Checks if the object does exist |
||||
|
* |
||||
|
* @return true if the object does exist |
||||
|
*/ |
||||
|
public boolean doesExist() { |
||||
|
try { |
||||
|
FileSystem dfs = HdfsOverFtpSystem.getDfs(); |
||||
|
dfs.getFileStatus(fullPath); |
||||
|
return true; |
||||
|
} catch (IOException e) { |
||||
|
// log.debug(path + " does not exist", e); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public boolean isReadable() { |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
public boolean isWritable() { |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
public boolean isRemovable() { |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get owner of the object |
||||
|
* |
||||
|
* @return owner of the object |
||||
|
*/ |
||||
|
public String getOwnerName() { |
||||
|
return "root"; |
||||
|
/* |
||||
|
try { |
||||
|
FileSystem dfs = HdfsOverFtpSystem.getDfs(); |
||||
|
FileStatus fs = dfs.getFileStatus(fullPath); |
||||
|
String owner = fs.getOwner(); |
||||
|
if(owner.length() == 0) { |
||||
|
return "root"; |
||||
|
} |
||||
|
return owner; |
||||
|
} catch (IOException e) { |
||||
|
e.printStackTrace(); |
||||
|
return null; |
||||
|
} |
||||
|
*/ |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get group of the object |
||||
|
* |
||||
|
* @return group of the object |
||||
|
*/ |
||||
|
public String getGroupName() { |
||||
|
return "root"; |
||||
|
/* |
||||
|
try { |
||||
|
FileSystem dfs = HdfsOverFtpSystem.getDfs(); |
||||
|
FileStatus fs = dfs.getFileStatus(fullPath); |
||||
|
String group = fs.getGroup(); |
||||
|
if(group.length() == 0) { |
||||
|
return "root"; |
||||
|
} |
||||
|
return group; |
||||
|
} catch (IOException e) { |
||||
|
e.printStackTrace(); |
||||
|
return null; |
||||
|
} |
||||
|
*/ |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get link count |
||||
|
* |
||||
|
* @return 3 is for a directory and 1 is for a file |
||||
|
*/ |
||||
|
public int getLinkCount() { |
||||
|
return isDirectory() ? 3 : 1; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get last modification date |
||||
|
* |
||||
|
* @return last modification date as a long |
||||
|
*/ |
||||
|
public long getLastModified() { |
||||
|
try { |
||||
|
FileSystem dfs = HdfsOverFtpSystem.getDfs(); |
||||
|
FileStatus fs = dfs.getFileStatus(fullPath); |
||||
|
return fs.getModificationTime(); |
||||
|
} catch (IOException e) { |
||||
|
e.printStackTrace(); |
||||
|
return 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public boolean setLastModified(long l) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get a size of the object |
||||
|
* |
||||
|
* @return size of the object in bytes |
||||
|
*/ |
||||
|
public long getSize() { |
||||
|
try { |
||||
|
FileSystem dfs = HdfsOverFtpSystem.getDfs(); |
||||
|
FileStatus fs = dfs.getFileStatus(fullPath); |
||||
|
log.debug("getSize(): " + fullPath + " : " + fs.getLen()); |
||||
|
return fs.getLen(); |
||||
|
} catch (IOException e) { |
||||
|
e.printStackTrace(); |
||||
|
return 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public Object getPhysicalFile() { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Create a new dir from the object |
||||
|
* |
||||
|
* @return true if dir is created |
||||
|
*/ |
||||
|
public boolean mkdir() { |
||||
|
try { |
||||
|
FileSystem fs = HdfsOverFtpSystem.getDfs(); |
||||
|
fs.mkdirs(fullPath); |
||||
|
// fs.setOwner(path, user.getName(), user.getMainGroup()); |
||||
|
return true; |
||||
|
} catch (IOException e) { |
||||
|
e.printStackTrace(); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Delete object from the HDFS filesystem |
||||
|
* |
||||
|
* @return true if the object is deleted |
||||
|
*/ |
||||
|
public boolean delete() { |
||||
|
try { |
||||
|
FileSystem dfs = HdfsOverFtpSystem.getDfs(); |
||||
|
dfs.delete(fullPath, true); |
||||
|
return true; |
||||
|
} catch (IOException e) { |
||||
|
e.printStackTrace(); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public boolean move(FtpFile ftpFile) { |
||||
|
try { |
||||
|
FileSystem dfs = HdfsOverFtpSystem.getDfs(); |
||||
|
dfs.rename(fullPath, new Path(fullPath.getParent() + File.separator + ftpFile.getName())); |
||||
|
return true; |
||||
|
} catch (IOException e) { |
||||
|
e.printStackTrace(); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* List files of the directory |
||||
|
* |
||||
|
* @return List of files in the directory |
||||
|
*/ |
||||
|
public List<FtpFile> listFiles() { |
||||
|
try { |
||||
|
FileSystem dfs = HdfsOverFtpSystem.getDfs(); |
||||
|
FileStatus fileStats[] = dfs.listStatus(fullPath); |
||||
|
|
||||
|
// get the virtual name of the base directory |
||||
|
String virtualFileStr = getAbsolutePath(); |
||||
|
if (virtualFileStr.charAt(virtualFileStr.length() - 1) != '/') { |
||||
|
virtualFileStr += '/'; |
||||
|
} |
||||
|
|
||||
|
FtpFile[] virtualFiles = new FtpFile[fileStats.length]; |
||||
|
for (int i = 0; i < fileStats.length; i++) { |
||||
|
File fileObj = new File(fileStats[i].getPath().toString()); |
||||
|
String fileName = virtualFileStr + fileObj.getName(); |
||||
|
virtualFiles[i] = new HdfsFileObject(homePath.toString(), fileName, user); |
||||
|
} |
||||
|
return Collections.unmodifiableList(Arrays.asList(virtualFiles)); |
||||
|
} catch (IOException e) { |
||||
|
log.debug("", e); |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Creates output stream to write to the object |
||||
|
* |
||||
|
* @param l is not used here |
||||
|
* @return OutputStream |
||||
|
* @throws IOException |
||||
|
*/ |
||||
|
public OutputStream createOutputStream(long l) { |
||||
|
try { |
||||
|
FileSystem fs = HdfsOverFtpSystem.getDfs(); |
||||
|
FSDataOutputStream out = fs.create(fullPath); |
||||
|
// fs.setOwner(fullPath, user.getName(), user.getMainGroup()); |
||||
|
return out; |
||||
|
} catch (IOException e) { |
||||
|
e.printStackTrace(); |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Creates input stream to read from the object |
||||
|
* |
||||
|
* @param l is not used here |
||||
|
* @return OutputStream |
||||
|
* @throws IOException |
||||
|
*/ |
||||
|
public InputStream createInputStream(long l) { |
||||
|
try { |
||||
|
FileSystem dfs = HdfsOverFtpSystem.getDfs(); |
||||
|
FSDataInputStream in = dfs.open(fullPath); |
||||
|
return in; |
||||
|
} catch (IOException e) { |
||||
|
e.printStackTrace(); |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
package org.apache.hadoop.seaweed.ftp.service.filesystem; |
||||
|
|
||||
|
import org.apache.ftpserver.ftplet.FileSystemFactory; |
||||
|
import org.apache.ftpserver.ftplet.FileSystemView; |
||||
|
import org.apache.ftpserver.ftplet.User; |
||||
|
|
||||
|
/** |
||||
|
* Impelented FileSystemManager to use HdfsFileSystemView |
||||
|
*/ |
||||
|
public class HdfsFileSystemManager implements FileSystemFactory { |
||||
|
public FileSystemView createFileSystemView(User user) { |
||||
|
return new HdfsFileSystemView(user); |
||||
|
} |
||||
|
} |
@ -0,0 +1,104 @@ |
|||||
|
package org.apache.hadoop.seaweed.ftp.service.filesystem; |
||||
|
|
||||
|
import org.apache.ftpserver.ftplet.FileSystemView; |
||||
|
import org.apache.ftpserver.ftplet.FtpFile; |
||||
|
import org.apache.ftpserver.ftplet.User; |
||||
|
import org.apache.hadoop.fs.Path; |
||||
|
|
||||
|
import java.io.File; |
||||
|
|
||||
|
/** |
||||
|
* Implemented FileSystemView to use HdfsFileObject |
||||
|
*/ |
||||
|
public class HdfsFileSystemView implements FileSystemView { |
||||
|
|
||||
|
private String homePath; |
||||
|
private String currPath = File.separator; |
||||
|
private User user; |
||||
|
|
||||
|
/** |
||||
|
* Constructor - set the user object. |
||||
|
*/ |
||||
|
protected HdfsFileSystemView(User user) { |
||||
|
if (user == null) { |
||||
|
throw new IllegalArgumentException("user can not be null"); |
||||
|
} |
||||
|
if (user.getHomeDirectory() == null) { |
||||
|
throw new IllegalArgumentException( |
||||
|
"User home directory can not be null"); |
||||
|
} |
||||
|
|
||||
|
this.homePath = user.getHomeDirectory(); |
||||
|
this.user = user; |
||||
|
} |
||||
|
|
||||
|
public FtpFile getHomeDirectory() { |
||||
|
return new HdfsFileObject(homePath, File.separator, user); |
||||
|
} |
||||
|
|
||||
|
public FtpFile getWorkingDirectory() { |
||||
|
FtpFile fileObj; |
||||
|
if (currPath.equals(File.separator)) { |
||||
|
fileObj = new HdfsFileObject(homePath, File.separator, user); |
||||
|
} else { |
||||
|
fileObj = new HdfsFileObject(homePath, currPath, user); |
||||
|
|
||||
|
} |
||||
|
return fileObj; |
||||
|
} |
||||
|
|
||||
|
public boolean changeWorkingDirectory(String dir) { |
||||
|
|
||||
|
Path path; |
||||
|
if (dir.startsWith(File.separator) || new Path(currPath).equals(new Path(dir))) { |
||||
|
path = new Path(dir); |
||||
|
} else if (currPath.length() > 1) { |
||||
|
path = new Path(currPath + File.separator + dir); |
||||
|
} else { |
||||
|
if(dir.startsWith("/")) { |
||||
|
path = new Path(dir); |
||||
|
}else { |
||||
|
path = new Path(File.separator + dir); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 防止退回根目录 |
||||
|
if (path.getName().equals("..")) { |
||||
|
path = new Path(File.separator); |
||||
|
} |
||||
|
|
||||
|
HdfsFileObject file = new HdfsFileObject(homePath, path.toString(), user); |
||||
|
if (file.isDirectory()) { |
||||
|
currPath = path.toString(); |
||||
|
return true; |
||||
|
} else { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public FtpFile getFile(String file) { |
||||
|
String path; |
||||
|
if (file.startsWith(File.separator)) { |
||||
|
path = file; |
||||
|
} else if (currPath.length() > 1) { |
||||
|
path = currPath + File.separator + file; |
||||
|
} else { |
||||
|
path = File.separator + file; |
||||
|
} |
||||
|
return new HdfsFileObject(homePath, path, user); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Is the file content random accessible? |
||||
|
*/ |
||||
|
public boolean isRandomAccessible() { |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Dispose file system view - does nothing. |
||||
|
*/ |
||||
|
public void dispose() { |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,72 @@ |
|||||
|
package org.apache.hadoop.seaweed.ftp.service.filesystem; |
||||
|
|
||||
|
import org.apache.hadoop.conf.Configuration; |
||||
|
import org.apache.hadoop.fs.FileSystem; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
|
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* Class to store DFS connection |
||||
|
*/ |
||||
|
public class HdfsOverFtpSystem { |
||||
|
|
||||
|
private static FileSystem fs = null; |
||||
|
|
||||
|
private static String hdfsUri; |
||||
|
|
||||
|
private static boolean seaweedFsEnable; |
||||
|
|
||||
|
private static String seaweedFsAccess; |
||||
|
|
||||
|
private static String seaweedFsReplication; |
||||
|
|
||||
|
private final static Logger log = LoggerFactory.getLogger(HdfsOverFtpSystem.class); |
||||
|
|
||||
|
private static void hdfsInit() throws IOException { |
||||
|
Configuration configuration = new Configuration(); |
||||
|
|
||||
|
configuration.set("fs.defaultFS", hdfsUri); |
||||
|
if(seaweedFsEnable) { |
||||
|
configuration.set("fs.seaweedfs.impl", "seaweed.hdfs.SeaweedFileSystem"); |
||||
|
configuration.set("fs.seaweed.volume.server.access", seaweedFsAccess); |
||||
|
configuration.set("fs.seaweed.replication", seaweedFsReplication); |
||||
|
} |
||||
|
fs = FileSystem.get(configuration); |
||||
|
log.info("HDFS load success"); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get dfs |
||||
|
* |
||||
|
* @return dfs |
||||
|
* @throws IOException |
||||
|
*/ |
||||
|
public static FileSystem getDfs() throws IOException { |
||||
|
if (fs == null) { |
||||
|
hdfsInit(); |
||||
|
} |
||||
|
return fs; |
||||
|
} |
||||
|
|
||||
|
public static void setHdfsUri(String hdfsUri) { |
||||
|
HdfsOverFtpSystem.hdfsUri = hdfsUri; |
||||
|
} |
||||
|
|
||||
|
public static String getHdfsUri() { |
||||
|
return hdfsUri; |
||||
|
} |
||||
|
|
||||
|
public static void setSeaweedFsEnable(boolean seaweedFsEnable) { |
||||
|
HdfsOverFtpSystem.seaweedFsEnable = seaweedFsEnable; |
||||
|
} |
||||
|
|
||||
|
public static void setSeaweedFsAccess(String seaweedFsAccess) { |
||||
|
HdfsOverFtpSystem.seaweedFsAccess = seaweedFsAccess; |
||||
|
} |
||||
|
|
||||
|
public static void setSeaweedFsReplication(String seaweedFsReplication) { |
||||
|
HdfsOverFtpSystem.seaweedFsReplication = seaweedFsReplication; |
||||
|
} |
||||
|
} |
@ -0,0 +1,239 @@ |
|||||
|
package org.apache.hadoop.seaweed.ftp.users; |
||||
|
|
||||
|
import org.apache.ftpserver.ftplet.Authority; |
||||
|
import org.apache.ftpserver.ftplet.AuthorizationRequest; |
||||
|
import org.apache.ftpserver.ftplet.User; |
||||
|
import org.apache.log4j.Logger; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.Collections; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public class HdfsUser implements User, Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = -47371353779731294L; |
||||
|
|
||||
|
private String name = null; |
||||
|
|
||||
|
private String password = null; |
||||
|
|
||||
|
private int maxIdleTimeSec = 0; // no limit |
||||
|
|
||||
|
private String homeDir = null; |
||||
|
|
||||
|
private boolean isEnabled = true; |
||||
|
|
||||
|
private List<? extends Authority> authorities = new ArrayList<Authority>(); |
||||
|
|
||||
|
private ArrayList<String> groups = new ArrayList<String>(); |
||||
|
|
||||
|
private Logger log = Logger.getLogger(HdfsUser.class); |
||||
|
|
||||
|
/** |
||||
|
* Default constructor. |
||||
|
*/ |
||||
|
public HdfsUser() { |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Copy constructor. |
||||
|
*/ |
||||
|
public HdfsUser(User user) { |
||||
|
name = user.getName(); |
||||
|
password = user.getPassword(); |
||||
|
authorities = user.getAuthorities(); |
||||
|
maxIdleTimeSec = user.getMaxIdleTime(); |
||||
|
homeDir = user.getHomeDirectory(); |
||||
|
isEnabled = user.getEnabled(); |
||||
|
} |
||||
|
|
||||
|
public ArrayList<String> getGroups() { |
||||
|
return groups; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get the main group of the user |
||||
|
* |
||||
|
* @return main group of the user |
||||
|
*/ |
||||
|
public String getMainGroup() { |
||||
|
if (groups.size() > 0) { |
||||
|
return groups.get(0); |
||||
|
} else { |
||||
|
log.error("User " + name + " is not a memer of any group"); |
||||
|
return "error"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Checks if user is a member of the group |
||||
|
* |
||||
|
* @param group to check |
||||
|
* @return true if the user id a member of the group |
||||
|
*/ |
||||
|
public boolean isGroupMember(String group) { |
||||
|
for (String userGroup : groups) { |
||||
|
if (userGroup.equals(group)) { |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Set users' groups |
||||
|
* |
||||
|
* @param groups to set |
||||
|
*/ |
||||
|
public void setGroups(ArrayList<String> groups) { |
||||
|
if (groups.size() < 1) { |
||||
|
log.error("User " + name + " is not a memer of any group"); |
||||
|
} |
||||
|
this.groups = groups; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get the user name. |
||||
|
*/ |
||||
|
public String getName() { |
||||
|
return name; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Set user name. |
||||
|
*/ |
||||
|
public void setName(String name) { |
||||
|
this.name = name; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get the user password. |
||||
|
*/ |
||||
|
public String getPassword() { |
||||
|
return password; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Set user password. |
||||
|
*/ |
||||
|
public void setPassword(String pass) { |
||||
|
password = pass; |
||||
|
} |
||||
|
|
||||
|
public List<Authority> getAuthorities() { |
||||
|
if (authorities != null) { |
||||
|
return Collections.unmodifiableList(authorities); |
||||
|
} else { |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void setAuthorities(List<Authority> authorities) { |
||||
|
if (authorities != null) { |
||||
|
this.authorities = Collections.unmodifiableList(authorities); |
||||
|
} else { |
||||
|
this.authorities = null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get the maximum idle time in second. |
||||
|
*/ |
||||
|
public int getMaxIdleTime() { |
||||
|
return maxIdleTimeSec; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Set the maximum idle time in second. |
||||
|
*/ |
||||
|
public void setMaxIdleTime(int idleSec) { |
||||
|
maxIdleTimeSec = idleSec; |
||||
|
if (maxIdleTimeSec < 0) { |
||||
|
maxIdleTimeSec = 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get the user enable status. |
||||
|
*/ |
||||
|
public boolean getEnabled() { |
||||
|
return isEnabled; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Set the user enable status. |
||||
|
*/ |
||||
|
public void setEnabled(boolean enb) { |
||||
|
isEnabled = enb; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get the user home directory. |
||||
|
*/ |
||||
|
public String getHomeDirectory() { |
||||
|
return homeDir; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Set the user home directory. |
||||
|
*/ |
||||
|
public void setHomeDirectory(String home) { |
||||
|
homeDir = home; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* String representation. |
||||
|
*/ |
||||
|
public String toString() { |
||||
|
return name; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritDoc} |
||||
|
*/ |
||||
|
public AuthorizationRequest authorize(AuthorizationRequest request) { |
||||
|
List<Authority> authorities = getAuthorities(); |
||||
|
|
||||
|
// check for no authorities at all |
||||
|
if (authorities == null) { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
boolean someoneCouldAuthorize = false; |
||||
|
for (Authority authority : authorities) { |
||||
|
if (authority.canAuthorize(request)) { |
||||
|
someoneCouldAuthorize = true; |
||||
|
|
||||
|
request = authority.authorize(request); |
||||
|
|
||||
|
// authorization failed, return null |
||||
|
if (request == null) { |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
if (someoneCouldAuthorize) { |
||||
|
return request; |
||||
|
} else { |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritDoc} |
||||
|
*/ |
||||
|
public List<Authority> getAuthorities(Class<? extends Authority> clazz) { |
||||
|
List<Authority> selected = new ArrayList<Authority>(); |
||||
|
|
||||
|
for (Authority authority : authorities) { |
||||
|
if (authority.getClass().equals(clazz)) { |
||||
|
selected.add(authority); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return selected; |
||||
|
} |
||||
|
} |
@ -0,0 +1,453 @@ |
|||||
|
package org.apache.hadoop.seaweed.ftp.users; |
||||
|
|
||||
|
import org.apache.ftpserver.FtpServerConfigurationException; |
||||
|
import org.apache.ftpserver.ftplet.*; |
||||
|
import org.apache.ftpserver.usermanager.*; |
||||
|
import org.apache.ftpserver.usermanager.impl.*; |
||||
|
import org.apache.ftpserver.util.BaseProperties; |
||||
|
import org.apache.ftpserver.util.IoUtils; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
|
||||
|
import java.io.File; |
||||
|
import java.io.FileInputStream; |
||||
|
import java.io.FileOutputStream; |
||||
|
import java.io.IOException; |
||||
|
import java.util.*; |
||||
|
|
||||
|
public class HdfsUserManager extends AbstractUserManager { |
||||
|
|
||||
|
private final Logger LOG = LoggerFactory |
||||
|
.getLogger(HdfsUserManager.class); |
||||
|
|
||||
|
private final static String DEPRECATED_PREFIX = "FtpServer.user."; |
||||
|
|
||||
|
private final static String PREFIX = "ftpserver.user."; |
||||
|
|
||||
|
private static BaseProperties userDataProp; |
||||
|
|
||||
|
private File userDataFile = new File("users.conf"); |
||||
|
|
||||
|
private boolean isConfigured = false; |
||||
|
|
||||
|
private PasswordEncryptor passwordEncryptor = new Md5PasswordEncryptor(); |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Retrieve the file used to load and store users |
||||
|
* |
||||
|
* @return The file |
||||
|
*/ |
||||
|
public File getFile() { |
||||
|
return userDataFile; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Set the file used to store and read users. Must be set before |
||||
|
* {@link #configure()} is called. |
||||
|
* |
||||
|
* @param propFile A file containing users |
||||
|
*/ |
||||
|
public void setFile(File propFile) { |
||||
|
if (isConfigured) { |
||||
|
throw new IllegalStateException("Must be called before configure()"); |
||||
|
} |
||||
|
|
||||
|
this.userDataFile = propFile; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Retrieve the password encryptor used for this user manager |
||||
|
* |
||||
|
* @return The password encryptor. Default to {@link Md5PasswordEncryptor} |
||||
|
* if no other has been provided |
||||
|
*/ |
||||
|
public PasswordEncryptor getPasswordEncryptor() { |
||||
|
return passwordEncryptor; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Set the password encryptor to use for this user manager |
||||
|
* |
||||
|
* @param passwordEncryptor The password encryptor |
||||
|
*/ |
||||
|
public void setPasswordEncryptor(PasswordEncryptor passwordEncryptor) { |
||||
|
this.passwordEncryptor = passwordEncryptor; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Lazy init the user manager |
||||
|
*/ |
||||
|
private void lazyInit() { |
||||
|
if (!isConfigured) { |
||||
|
configure(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Configure user manager. |
||||
|
*/ |
||||
|
public void configure() { |
||||
|
isConfigured = true; |
||||
|
try { |
||||
|
userDataProp = new BaseProperties(); |
||||
|
|
||||
|
if (userDataFile != null && userDataFile.exists()) { |
||||
|
FileInputStream fis = null; |
||||
|
try { |
||||
|
fis = new FileInputStream(userDataFile); |
||||
|
userDataProp.load(fis); |
||||
|
} finally { |
||||
|
IoUtils.close(fis); |
||||
|
} |
||||
|
} |
||||
|
} catch (IOException e) { |
||||
|
throw new FtpServerConfigurationException( |
||||
|
"Error loading user data file : " |
||||
|
+ userDataFile.getAbsolutePath(), e); |
||||
|
} |
||||
|
|
||||
|
convertDeprecatedPropertyNames(); |
||||
|
} |
||||
|
|
||||
|
private void convertDeprecatedPropertyNames() { |
||||
|
Enumeration<?> keys = userDataProp.propertyNames(); |
||||
|
|
||||
|
boolean doSave = false; |
||||
|
|
||||
|
while (keys.hasMoreElements()) { |
||||
|
String key = (String) keys.nextElement(); |
||||
|
|
||||
|
if (key.startsWith(DEPRECATED_PREFIX)) { |
||||
|
String newKey = PREFIX |
||||
|
+ key.substring(DEPRECATED_PREFIX.length()); |
||||
|
userDataProp.setProperty(newKey, userDataProp.getProperty(key)); |
||||
|
userDataProp.remove(key); |
||||
|
|
||||
|
doSave = true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (doSave) { |
||||
|
try { |
||||
|
saveUserData(); |
||||
|
} catch (FtpException e) { |
||||
|
throw new FtpServerConfigurationException( |
||||
|
"Failed to save updated user data", e); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public synchronized void save(User usr, boolean renamePush) throws FtpException { |
||||
|
lazyInit(); |
||||
|
userDataProp.setProperty(PREFIX + usr.getName() + ".rename.push", renamePush); |
||||
|
save(usr); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Save user data. Store the properties. |
||||
|
*/ |
||||
|
public synchronized void save(User usr) throws FtpException { |
||||
|
lazyInit(); |
||||
|
|
||||
|
// null value check |
||||
|
if (usr.getName() == null) { |
||||
|
throw new NullPointerException("User name is null."); |
||||
|
} |
||||
|
String thisPrefix = PREFIX + usr.getName() + '.'; |
||||
|
|
||||
|
// set other properties |
||||
|
userDataProp.setProperty(thisPrefix + ATTR_PASSWORD, getPassword(usr)); |
||||
|
|
||||
|
String home = usr.getHomeDirectory(); |
||||
|
if (home == null) { |
||||
|
home = "/"; |
||||
|
} |
||||
|
userDataProp.setProperty(thisPrefix + ATTR_HOME, home); |
||||
|
userDataProp.setProperty(thisPrefix + ATTR_ENABLE, usr.getEnabled()); |
||||
|
userDataProp.setProperty(thisPrefix + ATTR_WRITE_PERM, usr |
||||
|
.authorize(new WriteRequest()) != null); |
||||
|
userDataProp.setProperty(thisPrefix + ATTR_MAX_IDLE_TIME, usr |
||||
|
.getMaxIdleTime()); |
||||
|
|
||||
|
TransferRateRequest transferRateRequest = new TransferRateRequest(); |
||||
|
transferRateRequest = (TransferRateRequest) usr |
||||
|
.authorize(transferRateRequest); |
||||
|
|
||||
|
if (transferRateRequest != null) { |
||||
|
userDataProp.setProperty(thisPrefix + ATTR_MAX_UPLOAD_RATE, |
||||
|
transferRateRequest.getMaxUploadRate()); |
||||
|
userDataProp.setProperty(thisPrefix + ATTR_MAX_DOWNLOAD_RATE, |
||||
|
transferRateRequest.getMaxDownloadRate()); |
||||
|
} else { |
||||
|
userDataProp.remove(thisPrefix + ATTR_MAX_UPLOAD_RATE); |
||||
|
userDataProp.remove(thisPrefix + ATTR_MAX_DOWNLOAD_RATE); |
||||
|
} |
||||
|
|
||||
|
// request that always will succeed |
||||
|
ConcurrentLoginRequest concurrentLoginRequest = new ConcurrentLoginRequest( |
||||
|
0, 0); |
||||
|
concurrentLoginRequest = (ConcurrentLoginRequest) usr |
||||
|
.authorize(concurrentLoginRequest); |
||||
|
|
||||
|
if (concurrentLoginRequest != null) { |
||||
|
userDataProp.setProperty(thisPrefix + ATTR_MAX_LOGIN_NUMBER, |
||||
|
concurrentLoginRequest.getMaxConcurrentLogins()); |
||||
|
userDataProp.setProperty(thisPrefix + ATTR_MAX_LOGIN_PER_IP, |
||||
|
concurrentLoginRequest.getMaxConcurrentLoginsPerIP()); |
||||
|
} else { |
||||
|
userDataProp.remove(thisPrefix + ATTR_MAX_LOGIN_NUMBER); |
||||
|
userDataProp.remove(thisPrefix + ATTR_MAX_LOGIN_PER_IP); |
||||
|
} |
||||
|
|
||||
|
saveUserData(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @throws FtpException |
||||
|
*/ |
||||
|
private void saveUserData() throws FtpException { |
||||
|
File dir = userDataFile.getAbsoluteFile().getParentFile(); |
||||
|
if (dir != null && !dir.exists() && !dir.mkdirs()) { |
||||
|
String dirName = dir.getAbsolutePath(); |
||||
|
throw new FtpServerConfigurationException( |
||||
|
"Cannot create directory for user data file : " + dirName); |
||||
|
} |
||||
|
|
||||
|
// save user data |
||||
|
FileOutputStream fos = null; |
||||
|
try { |
||||
|
fos = new FileOutputStream(userDataFile); |
||||
|
userDataProp.store(fos, "Generated file - don't edit (please)"); |
||||
|
} catch (IOException ex) { |
||||
|
LOG.error("Failed saving user data", ex); |
||||
|
throw new FtpException("Failed saving user data", ex); |
||||
|
} finally { |
||||
|
IoUtils.close(fos); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public synchronized void list() throws FtpException { |
||||
|
lazyInit(); |
||||
|
|
||||
|
Map dataMap = new HashMap(); |
||||
|
Enumeration<String> propNames = (Enumeration<String>) userDataProp.propertyNames(); |
||||
|
ArrayList<String> a = Collections.list(propNames); |
||||
|
a.remove("i18nMap");//去除i18nMap |
||||
|
for(String attrName : a){ |
||||
|
// dataMap.put(attrName, propNames.); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Delete an user. Removes all this user entries from the properties. After |
||||
|
* removing the corresponding from the properties, save the data. |
||||
|
*/ |
||||
|
public synchronized void delete(String usrName) throws FtpException { |
||||
|
lazyInit(); |
||||
|
|
||||
|
// remove entries from properties |
||||
|
String thisPrefix = PREFIX + usrName + '.'; |
||||
|
Enumeration<?> propNames = userDataProp.propertyNames(); |
||||
|
ArrayList<String> remKeys = new ArrayList<String>(); |
||||
|
while (propNames.hasMoreElements()) { |
||||
|
String thisKey = propNames.nextElement().toString(); |
||||
|
if (thisKey.startsWith(thisPrefix)) { |
||||
|
remKeys.add(thisKey); |
||||
|
} |
||||
|
} |
||||
|
Iterator<String> remKeysIt = remKeys.iterator(); |
||||
|
while (remKeysIt.hasNext()) { |
||||
|
userDataProp.remove(remKeysIt.next()); |
||||
|
} |
||||
|
|
||||
|
saveUserData(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get user password. Returns the encrypted value. |
||||
|
* <p/> |
||||
|
* <pre> |
||||
|
* If the password value is not null |
||||
|
* password = new password |
||||
|
* else |
||||
|
* if user does exist |
||||
|
* password = old password |
||||
|
* else |
||||
|
* password = "" |
||||
|
* </pre> |
||||
|
*/ |
||||
|
private String getPassword(User usr) { |
||||
|
String name = usr.getName(); |
||||
|
String password = usr.getPassword(); |
||||
|
|
||||
|
if (password != null) { |
||||
|
password = passwordEncryptor.encrypt(password); |
||||
|
} else { |
||||
|
String blankPassword = passwordEncryptor.encrypt(""); |
||||
|
|
||||
|
if (doesExist(name)) { |
||||
|
String key = PREFIX + name + '.' + ATTR_PASSWORD; |
||||
|
password = userDataProp.getProperty(key, blankPassword); |
||||
|
} else { |
||||
|
password = blankPassword; |
||||
|
} |
||||
|
} |
||||
|
return password; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get all user names. |
||||
|
*/ |
||||
|
public synchronized String[] getAllUserNames() { |
||||
|
lazyInit(); |
||||
|
|
||||
|
// get all user names |
||||
|
String suffix = '.' + ATTR_HOME; |
||||
|
ArrayList<String> ulst = new ArrayList<String>(); |
||||
|
Enumeration<?> allKeys = userDataProp.propertyNames(); |
||||
|
int prefixlen = PREFIX.length(); |
||||
|
int suffixlen = suffix.length(); |
||||
|
while (allKeys.hasMoreElements()) { |
||||
|
String key = (String) allKeys.nextElement(); |
||||
|
if (key.endsWith(suffix)) { |
||||
|
String name = key.substring(prefixlen); |
||||
|
int endIndex = name.length() - suffixlen; |
||||
|
name = name.substring(0, endIndex); |
||||
|
ulst.add(name); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Collections.sort(ulst); |
||||
|
return ulst.toArray(new String[0]); |
||||
|
} |
||||
|
|
||||
|
private ArrayList<String> parseGroups(String groupsLine) { |
||||
|
String groupsArray[] = groupsLine.split(","); |
||||
|
return new ArrayList(Arrays.asList(groupsArray)); |
||||
|
} |
||||
|
|
||||
|
public static synchronized boolean getUserRenamePush(String userName) { |
||||
|
return userDataProp.getBoolean(PREFIX + userName + ".rename.push", false); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Load user data. |
||||
|
*/ |
||||
|
public synchronized User getUserByName(String userName) { |
||||
|
lazyInit(); |
||||
|
|
||||
|
if (!doesExist(userName)) { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
String baseKey = PREFIX + userName + '.'; |
||||
|
HdfsUser user = new HdfsUser(); |
||||
|
user.setName(userName); |
||||
|
user.setEnabled(userDataProp.getBoolean(baseKey + ATTR_ENABLE, true)); |
||||
|
user.setHomeDirectory(userDataProp |
||||
|
.getProperty(baseKey + ATTR_HOME, "/")); |
||||
|
|
||||
|
// user.setGroups(parseGroups(userDataProp |
||||
|
// .getProperty(baseKey + "groups"))); |
||||
|
|
||||
|
List<Authority> authorities = new ArrayList<Authority>(); |
||||
|
|
||||
|
if (userDataProp.getBoolean(baseKey + ATTR_WRITE_PERM, false)) { |
||||
|
authorities.add(new WritePermission()); |
||||
|
} |
||||
|
|
||||
|
int maxLogin = userDataProp.getInteger(baseKey + ATTR_MAX_LOGIN_NUMBER, |
||||
|
0); |
||||
|
int maxLoginPerIP = userDataProp.getInteger(baseKey |
||||
|
+ ATTR_MAX_LOGIN_PER_IP, 0); |
||||
|
|
||||
|
authorities.add(new ConcurrentLoginPermission(maxLogin, maxLoginPerIP)); |
||||
|
|
||||
|
int uploadRate = userDataProp.getInteger( |
||||
|
baseKey + ATTR_MAX_UPLOAD_RATE, 0); |
||||
|
int downloadRate = userDataProp.getInteger(baseKey |
||||
|
+ ATTR_MAX_DOWNLOAD_RATE, 0); |
||||
|
|
||||
|
authorities.add(new TransferRatePermission(downloadRate, uploadRate)); |
||||
|
|
||||
|
user.setAuthorities(authorities); |
||||
|
|
||||
|
user.setMaxIdleTime(userDataProp.getInteger(baseKey |
||||
|
+ ATTR_MAX_IDLE_TIME, 0)); |
||||
|
|
||||
|
return user; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* User existance check |
||||
|
*/ |
||||
|
public synchronized boolean doesExist(String name) { |
||||
|
lazyInit(); |
||||
|
|
||||
|
String key = PREFIX + name + '.' + ATTR_HOME; |
||||
|
return userDataProp.containsKey(key); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* User authenticate method |
||||
|
*/ |
||||
|
public synchronized User authenticate(Authentication authentication) |
||||
|
throws AuthenticationFailedException { |
||||
|
lazyInit(); |
||||
|
|
||||
|
if (authentication instanceof UsernamePasswordAuthentication) { |
||||
|
UsernamePasswordAuthentication upauth = (UsernamePasswordAuthentication) authentication; |
||||
|
|
||||
|
String user = upauth.getUsername(); |
||||
|
String password = upauth.getPassword(); |
||||
|
|
||||
|
if (user == null) { |
||||
|
throw new AuthenticationFailedException("Authentication failed"); |
||||
|
} |
||||
|
|
||||
|
if (password == null) { |
||||
|
password = ""; |
||||
|
} |
||||
|
|
||||
|
String storedPassword = userDataProp.getProperty(PREFIX + user + '.' |
||||
|
+ ATTR_PASSWORD); |
||||
|
|
||||
|
if (storedPassword == null) { |
||||
|
// user does not exist |
||||
|
throw new AuthenticationFailedException("Authentication failed"); |
||||
|
} |
||||
|
|
||||
|
if (passwordEncryptor.matches(password, storedPassword)) { |
||||
|
return getUserByName(user); |
||||
|
} else { |
||||
|
throw new AuthenticationFailedException("Authentication failed"); |
||||
|
} |
||||
|
|
||||
|
} else if (authentication instanceof AnonymousAuthentication) { |
||||
|
if (doesExist("anonymous")) { |
||||
|
return getUserByName("anonymous"); |
||||
|
} else { |
||||
|
throw new AuthenticationFailedException("Authentication failed"); |
||||
|
} |
||||
|
} else { |
||||
|
throw new IllegalArgumentException( |
||||
|
"Authentication not supported by this user manager"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Close the user manager - remove existing entries. |
||||
|
*/ |
||||
|
public synchronized void dispose() { |
||||
|
if (userDataProp != null) { |
||||
|
userDataProp.clear(); |
||||
|
userDataProp = null; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
server: |
||||
|
port: 8080 |
||||
|
|
||||
|
ftp: |
||||
|
port: 2222 |
||||
|
passive-address: localhost |
||||
|
passive-ports: 30000-30999 |
||||
|
|
||||
|
hdfs: |
||||
|
uri: seaweedfs://localhost:8888 |
||||
|
|
||||
|
seaweedFs: |
||||
|
enable: true |
||||
|
access: direct # direct/filerProxy/publicUrl |
||||
|
replication: "000" |
@ -0,0 +1,39 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
|
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd"> |
||||
|
|
||||
|
<id>package</id> |
||||
|
<formats> |
||||
|
<!-- 指定打包格式,支持的打包格式有zip、tar、tar.gz (or tgz)、tar.bz2 (or tbz2)、jar、dir、war,可以同时指定多个打包格式 --> |
||||
|
<format>tar.gz</format> |
||||
|
</formats> |
||||
|
<includeBaseDirectory>false</includeBaseDirectory> |
||||
|
|
||||
|
<fileSets> |
||||
|
<fileSet> |
||||
|
<directory>src/main/resources</directory> |
||||
|
<outputDirectory>/</outputDirectory> |
||||
|
<includes> |
||||
|
<include>application.yml</include> |
||||
|
<include>logback-spring.xml</include> |
||||
|
<include>users.properties</include> |
||||
|
<include>kafka-producer.properties</include> |
||||
|
</includes> |
||||
|
</fileSet> |
||||
|
<fileSet> |
||||
|
<directory>${project.build.directory}</directory> |
||||
|
<outputDirectory>/</outputDirectory> |
||||
|
<includes> |
||||
|
<include>*.jar</include> |
||||
|
</includes> |
||||
|
</fileSet> |
||||
|
</fileSets> |
||||
|
<dependencySets> |
||||
|
<dependencySet> |
||||
|
<useProjectArtifact>false</useProjectArtifact> |
||||
|
<outputDirectory>lib</outputDirectory> |
||||
|
<scope>runtime</scope> |
||||
|
<unpack>false</unpack> |
||||
|
</dependencySet> |
||||
|
</dependencySets> |
||||
|
</assembly> |
@ -0,0 +1,40 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" ?> |
||||
|
<configuration> |
||||
|
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径--> |
||||
|
<property name="LOG_HOME" value="${user.dir}/logs/" /> |
||||
|
|
||||
|
<!-- 控制台输出 --> |
||||
|
<appender name="Stdout" class="ch.qos.logback.core.ConsoleAppender"> |
||||
|
<!-- 日志输出编码 --> |
||||
|
<layout class="ch.qos.logback.classic.PatternLayout"> |
||||
|
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--> |
||||
|
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n |
||||
|
</pattern> |
||||
|
</layout> |
||||
|
</appender> |
||||
|
|
||||
|
<!-- 按照每天生成日志文件 --> |
||||
|
<appender name="RollingFile" |
||||
|
class="ch.qos.logback.core.rolling.RollingFileAppender"> |
||||
|
<File>${LOG_HOME}/fileLog.log</File> |
||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> |
||||
|
<fileNamePattern>${LOG_HOME}/fileLog.log.%d.%i</fileNamePattern> |
||||
|
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> |
||||
|
<maxFileSize>100 MB</maxFileSize> |
||||
|
</timeBasedFileNamingAndTriggeringPolicy> |
||||
|
</rollingPolicy> |
||||
|
<encoder> |
||||
|
<pattern> |
||||
|
%d %p (%file:%line\)- %m%n |
||||
|
</pattern> |
||||
|
<charset>UTF-8</charset> |
||||
|
</encoder> |
||||
|
</appender> |
||||
|
|
||||
|
<!-- 日志输出级别 --> |
||||
|
<root level="info"> |
||||
|
<appender-ref ref="Stdout" /> |
||||
|
<appender-ref ref="RollingFile" /> |
||||
|
</root> |
||||
|
|
||||
|
</configuration> |
@ -0,0 +1,12 @@ |
|||||
|
#Generated file - don't edit (please) |
||||
|
#Thu Mar 11 19:11:12 CST 2021 |
||||
|
ftpserver.user.test.idletime=0 |
||||
|
ftpserver.user.test.maxloginperip=0 |
||||
|
ftpserver.user.test.userpassword=44664D4D827C740293D2AA244FB60445 |
||||
|
ftpserver.user.test.enableflag=true |
||||
|
ftpserver.user.test.maxloginnumber=0 |
||||
|
ftpserver.user.test.rename.push=true |
||||
|
ftpserver.user.test.homedirectory=/buckets/test/ |
||||
|
ftpserver.user.test.downloadrate=0 |
||||
|
ftpserver.user.test.writepermission=true |
||||
|
ftpserver.user.test.uploadrate=0 |
Write
Preview
Loading…
Cancel
Save
Reference in new issue