Skip to content

Commit c8f7853

Browse files
DImuthuUpelahirujayathilake
authored andcommitted
File server initial implementation
1 parent ec4a624 commit c8f7853

File tree

19 files changed

+918
-3
lines changed

19 files changed

+918
-3
lines changed

modules/agent-framework/agent-service/pom.xml

+1-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
<maven.compiler.source>11</maven.compiler.source>
1616
<maven.compiler.target>11</maven.compiler.target>
1717
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18-
<spring.boot.version>3.2.4</spring.boot.version>
1918
<jul-to-slf4j.version>1.7.0</jul-to-slf4j.version>
2019
<json.version>20240303</json.version>
2120
<javax.version>2.0.1.Final</javax.version>
@@ -190,4 +189,4 @@
190189
</plugins>
191190
</build>
192191

193-
</project>
192+
</project>

modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/AiravataTask.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ public void init(HelixManager manager, String workflowName, String jobName, Stri
496496
}
497497
}
498498

499-
private void loadContext() throws TaskOnFailException {
499+
protected void loadContext() throws TaskOnFailException {
500500
try {
501501
logger.info("Loading context for task " + getTaskId());
502502
processModel = getRegistryServiceClient().getProcess(processId);

modules/file-server/pom.xml

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<parent>
5+
<groupId>org.apache.airavata</groupId>
6+
<artifactId>airavata</artifactId>
7+
<version>0.21-SNAPSHOT</version>
8+
<relativePath>../../pom.xml</relativePath>
9+
</parent>
10+
<artifactId>file-server</artifactId>
11+
<name>airavata-file-server</name>
12+
13+
<dependencies>
14+
<dependency>
15+
<groupId>org.springframework.boot</groupId>
16+
<artifactId>spring-boot-starter-web</artifactId>
17+
<version>${spring.boot.version}</version>
18+
<exclusions>
19+
<exclusion>
20+
<groupId>org.apache.logging.log4j</groupId>
21+
<artifactId>log4j-to-slf4j</artifactId>
22+
</exclusion>
23+
</exclusions>
24+
</dependency>
25+
<dependency>
26+
<groupId>org.apache.airavata</groupId>
27+
<artifactId>task-core</artifactId>
28+
<version>${project.version}</version>
29+
</dependency>
30+
<dependency>
31+
<groupId>org.apache.airavata</groupId>
32+
<artifactId>helix-spectator</artifactId>
33+
<version>${project.version}</version>
34+
</dependency>
35+
</dependencies>
36+
37+
<build>
38+
<plugins>
39+
<plugin>
40+
<groupId>org.springframework.boot</groupId>
41+
<artifactId>spring-boot-maven-plugin</artifactId>
42+
</plugin>
43+
<plugin>
44+
<groupId>org.apache.maven.plugins</groupId>
45+
<artifactId>maven-compiler-plugin</artifactId>
46+
<version>3.8.1</version>
47+
<configuration>
48+
<compilerArgs>
49+
<arg>-parameters</arg>
50+
</compilerArgs>
51+
</configuration>
52+
</plugin>
53+
<plugin>
54+
<groupId>org.apache.maven.plugins</groupId>
55+
<artifactId>maven-assembly-plugin</artifactId>
56+
<version>${maven.assembly.plugin}</version>
57+
<executions>
58+
<execution>
59+
<id>file-service-distribution-package</id>
60+
<phase>package</phase>
61+
<goals>
62+
<goal>single</goal>
63+
</goals>
64+
<configuration>
65+
<tarLongFileMode>posix</tarLongFileMode>
66+
<finalName>${file.service.dist.name}</finalName>
67+
<descriptors>
68+
<descriptor>src/main/assembly/file-service-bin-assembly.xml</descriptor>
69+
</descriptors>
70+
<attach>false</attach>
71+
</configuration>
72+
</execution>
73+
</executions>
74+
</plugin>
75+
</plugins>
76+
</build>
77+
78+
<properties>
79+
<file.service.dist.name>File-Service-0.01</file.service.dist.name>
80+
</properties>
81+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
2+
<!--
3+
4+
Licensed to the Apache Software Foundation (ASF) under one
5+
or more contributor license agreements. See the NOTICE file
6+
distributed with this work for additional information
7+
regarding copyright ownership. The ASF licenses this file
8+
to you under the Apache License, Version 2.0 (the
9+
"License"); you may not use this file except in compliance
10+
with the License. You may obtain a copy of the License at
11+
12+
http://www.apache.org/licenses/LICENSE-2.0
13+
14+
Unless required by applicable law or agreed to in writing,
15+
software distributed under the License is distributed on an
16+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
KIND, either express or implied. See the License for the
18+
specific language governing permissions and limitations
19+
under the License.
20+
21+
-->
22+
<!DOCTYPE assembly [
23+
<!ELEMENT assembly (id|includeBaseDirectory|baseDirectory|formats|fileSets|dependencySets)*>
24+
<!ELEMENT id (#PCDATA)>
25+
<!ELEMENT includeBaseDirectory (#PCDATA)>
26+
<!ELEMENT baseDirectory (#PCDATA)>
27+
<!ELEMENT formats (format)*>
28+
<!ELEMENT format (#PCDATA)>
29+
<!ELEMENT fileSets (fileSet)*>
30+
<!ELEMENT fileSet (directory|outputDirectory|fileMode|includes)*>
31+
<!ELEMENT directory (#PCDATA)>
32+
<!ELEMENT outputDirectory (#PCDATA)>
33+
<!ELEMENT includes (include)*>
34+
<!ELEMENT include (#PCDATA)>
35+
<!ELEMENT dependencySets (dependencySet)*>
36+
<!ELEMENT dependencySet (outputDirectory|outputFileNameMapping|includes)*>
37+
]>
38+
<assembly>
39+
<id>bin</id>
40+
<includeBaseDirectory>true</includeBaseDirectory>
41+
<baseDirectory>${file.service.dist.name}</baseDirectory>
42+
<formats>
43+
<format>tar.gz</format>
44+
<format>zip</format>
45+
</formats>
46+
47+
<fileSets>
48+
<fileSet>
49+
<directory>src/main/resources/distribution/bin</directory>
50+
<outputDirectory>bin</outputDirectory>
51+
<fileMode>777</fileMode>
52+
<includes>
53+
<include>*.sh</include>
54+
</includes>
55+
</fileSet>
56+
<fileSet>
57+
<directory>src/main/resources/distribution/conf</directory>
58+
<outputDirectory>conf</outputDirectory>
59+
<includes>
60+
<include>application.properties</include>
61+
<include>log4j2.xml</include>
62+
</includes>
63+
</fileSet>
64+
<fileSet>
65+
<directory>./</directory>
66+
<outputDirectory>logs</outputDirectory>
67+
<excludes>
68+
<exclude>*/**</exclude>
69+
</excludes>
70+
</fileSet>
71+
<fileSet>
72+
<directory>target</directory>
73+
<outputDirectory>lib</outputDirectory>
74+
<includes>
75+
<include>*.jar</include>
76+
</includes>
77+
</fileSet>
78+
</fileSets>
79+
80+
<dependencySets>
81+
<dependencySet>
82+
<useProjectArtifact>false</useProjectArtifact>
83+
<outputDirectory>lib</outputDirectory>
84+
<includes>
85+
<include>*</include>
86+
</includes>
87+
</dependencySet>
88+
</dependencySets>
89+
90+
</assembly>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.apache.airavata.file.server;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration;
6+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
7+
import org.springframework.context.annotation.ComponentScan;
8+
9+
@SpringBootApplication(scanBasePackages = "org.apache.airavata.file.server",
10+
exclude = {GroovyTemplateAutoConfiguration.class})
11+
@EnableConfigurationProperties(FileServerConfiguration.class)
12+
public class FileServerApplication {
13+
public static void main(String[] args) {
14+
SpringApplication.run(FileServerApplication.class, args);
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package org.apache.airavata.file.server;
2+
3+
import org.apache.airavata.common.utils.ServerSettings;
4+
import org.apache.airavata.common.utils.ThriftClientPool;
5+
import org.apache.airavata.helix.core.support.adaptor.AdaptorSupportImpl;
6+
import org.apache.airavata.helix.task.api.support.AdaptorSupport;
7+
import org.apache.airavata.registry.api.RegistryService;
8+
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
9+
import org.springframework.beans.factory.annotation.Value;
10+
import org.springframework.boot.context.properties.ConfigurationProperties;
11+
import org.springframework.context.annotation.Bean;
12+
import org.springframework.stereotype.Component;
13+
14+
@Component
15+
@ConfigurationProperties
16+
public class FileServerConfiguration {
17+
18+
@Bean
19+
public AdaptorSupport adaptorSupport() {
20+
return AdaptorSupportImpl.getInstance();
21+
}
22+
23+
//regserver.server.host
24+
@Value("${regserver.server.host:localhost}")
25+
private String registryServerHost;
26+
//regserver.server.port
27+
28+
@Value("${regserver.server.port:8970}")
29+
private int registryServerPort;
30+
31+
@Bean
32+
public ThriftClientPool<RegistryService.Client> registryClientPool() {
33+
GenericObjectPoolConfig<RegistryService.Client> poolConfig = new GenericObjectPoolConfig<>();
34+
poolConfig.setMaxTotal(100);
35+
poolConfig.setMinIdle(5);
36+
poolConfig.setBlockWhenExhausted(true);
37+
poolConfig.setTestOnBorrow(true);
38+
poolConfig.setTestWhileIdle(true);
39+
// must set timeBetweenEvictionRunsMillis since eviction doesn't run unless that is positive
40+
poolConfig.setTimeBetweenEvictionRunsMillis(5L * 60L * 1000L);
41+
poolConfig.setNumTestsPerEvictionRun(10);
42+
poolConfig.setMaxWaitMillis(3000);
43+
44+
return new ThriftClientPool<>(
45+
RegistryService.Client::new, poolConfig, registryServerHost, registryServerPort);
46+
}
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package org.apache.airavata.file.server.controller;
2+
3+
import org.apache.airavata.file.server.model.AiravataDirectory;
4+
import org.apache.airavata.file.server.model.FileUploadResponse;
5+
import org.apache.airavata.file.server.service.AirvataFileService;
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
import org.springframework.beans.factory.annotation.Autowired;
9+
import org.springframework.core.io.Resource;
10+
import org.springframework.core.io.UrlResource;
11+
import org.springframework.http.HttpHeaders;
12+
import org.springframework.http.ResponseEntity;
13+
import org.springframework.stereotype.Controller;
14+
import org.springframework.web.bind.annotation.*;
15+
import org.springframework.web.multipart.MultipartFile;
16+
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
17+
18+
import java.io.File;
19+
import java.nio.file.Path;
20+
21+
@Controller
22+
public class FileController {
23+
24+
private final static Logger logger = LoggerFactory.getLogger(FileController.class);
25+
26+
@Autowired
27+
private AirvataFileService fileService;
28+
29+
@GetMapping("/list/{live}/{processId}")
30+
@ResponseBody
31+
public Object listFilesRoot(@PathVariable String live,
32+
@PathVariable String processId) throws Exception {
33+
try {
34+
return fileService.listFiles(processId, "");
35+
} catch (Exception e) {
36+
logger.error("Failed to list files for path {} in process {}", "root path", processId, e);
37+
throw e;
38+
}
39+
}
40+
@GetMapping("/list/{live}/{processId}/{subPath}")
41+
@ResponseBody
42+
public Object listFiles(@PathVariable String live,
43+
@PathVariable String processId,
44+
@PathVariable String subPath) throws Exception {
45+
try {
46+
return fileService.listFiles(processId, subPath);
47+
} catch (Exception e) {
48+
logger.error("Failed to list files for path {} in process {}", subPath, processId, e);
49+
throw e;
50+
}
51+
}
52+
53+
@GetMapping("/download/{isLive}/{processId}/{subPath}")
54+
@ResponseBody
55+
public ResponseEntity downloadFile(@PathVariable String isLive,
56+
@PathVariable String processId,
57+
@PathVariable String subPath) {
58+
59+
try {
60+
Path localPath = fileService.downloadFile(processId, subPath);
61+
Resource resource = new UrlResource(localPath.toUri());
62+
return ResponseEntity.ok()
63+
.header(HttpHeaders.CONTENT_DISPOSITION,
64+
"attachment; filename=\"" + new File(subPath).getName() + "\"")
65+
.body(resource);
66+
} catch (Exception e) {
67+
return ResponseEntity.internalServerError()
68+
.body("An internal server error occurred: " + e.getMessage());
69+
}
70+
}
71+
72+
73+
@PostMapping("/upload-file")
74+
@ResponseBody
75+
public FileUploadResponse uploadFile(@RequestParam("file") MultipartFile file) {
76+
String name = "";
77+
78+
String uri = ServletUriComponentsBuilder.fromCurrentContextPath()
79+
.path("/download/")
80+
.path(name)
81+
.toUriString();
82+
83+
return new FileUploadResponse(name, uri, file.getContentType(), file.getSize());
84+
}
85+
86+
87+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package org.apache.airavata.file.server.model;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
public class AiravataDirectory {
7+
private String directoryName;
8+
private long createdTime;
9+
10+
private List<AiravataFile> innerFiles = new ArrayList<>();
11+
private List<AiravataDirectory> innerDirectories = new ArrayList<>();
12+
13+
public AiravataDirectory(String directoryName, long createdTime) {
14+
this.directoryName = directoryName;
15+
this.createdTime = createdTime;
16+
}
17+
18+
public String getDirectoryName() {
19+
return directoryName;
20+
}
21+
22+
public void setDirectoryName(String directoryName) {
23+
this.directoryName = directoryName;
24+
}
25+
26+
public long getCreatedTime() {
27+
return createdTime;
28+
}
29+
30+
public void setCreatedTime(long createdTime) {
31+
this.createdTime = createdTime;
32+
}
33+
34+
public List<AiravataFile> getInnerFiles() {
35+
return innerFiles;
36+
}
37+
38+
public void setInnerFiles(List<AiravataFile> innerFiles) {
39+
this.innerFiles = innerFiles;
40+
}
41+
42+
public List<AiravataDirectory> getInnerDirectories() {
43+
return innerDirectories;
44+
}
45+
46+
public void setInnerDirectories(List<AiravataDirectory> innerDirectories) {
47+
this.innerDirectories = innerDirectories;
48+
}
49+
}

0 commit comments

Comments
 (0)