From 003b045ac9027e56c0a306d246cb56da91d0e980 Mon Sep 17 00:00:00 2001 From: Lucas Bertrand-Christen <l.b-c@hotmail.com> Date: Wed, 15 Nov 2023 14:38:29 +0100 Subject: [PATCH] feat:td2-td3-wildflytxt --- .gitignore | 3 + TD2/.gitignore | 38 ++++ TD2/pom.xml | 65 ++++++ .../java/fr/ul/miage/td2/FilestoreAPI.java | 9 + .../fr/ul/miage/td2/HelloWorldResource.java | 18 ++ .../fr/ul/miage/td2/HelloWorldServlet.java | 19 ++ TD2/src/main/webapp/WEB-INF/web.xml | 16 ++ TD3/README.md | 12 ++ TD3/TD3.md | 10 + TD3/pom.xml | 81 ++++++++ .../filestore/api/FilestoreApplication.java | 8 + .../fr/miage23/filestore/api/dto/Hello.java | 14 ++ .../NodeNotFoundExceptionMapper.java | 16 ++ .../filestore/api/mapper/NodeHtmlMapper.java | 46 +++++ .../api/resources/NodesResource.java | 62 ++++++ .../miage23/filestore/files/FileService.java | 27 +++ .../files/InMemoryFileServiceBean.java | 147 +++++++++++++ .../miage23/filestore/files/entity/Node.java | 194 ++++++++++++++++++ .../files/exceptions/ContentException.java | 11 + .../NodeAlreadyExistsException.java | 7 + .../exceptions/NodeNotEmptyException.java | 7 + .../exceptions/NodeNotFoundException.java | 11 + .../files/exceptions/NodeTypeException.java | 7 + TD3/src/main/webapp/WEB-INF/web.xml | 8 + TD3/src/main/webapp/index.html | 8 + TD3/src/site/site.xml | 21 ++ allumer wildfly pour deploy.txt | 1 + 27 files changed, 866 insertions(+) create mode 100644 .gitignore create mode 100644 TD2/.gitignore create mode 100644 TD2/pom.xml create mode 100644 TD2/src/main/java/fr/ul/miage/td2/FilestoreAPI.java create mode 100644 TD2/src/main/java/fr/ul/miage/td2/HelloWorldResource.java create mode 100644 TD2/src/main/java/fr/ul/miage/td2/HelloWorldServlet.java create mode 100644 TD2/src/main/webapp/WEB-INF/web.xml create mode 100644 TD3/README.md create mode 100644 TD3/TD3.md create mode 100644 TD3/pom.xml create mode 100644 TD3/src/main/java/fr/miage23/filestore/api/FilestoreApplication.java create mode 100644 TD3/src/main/java/fr/miage23/filestore/api/dto/Hello.java create mode 100644 TD3/src/main/java/fr/miage23/filestore/api/exceptions/NodeNotFoundExceptionMapper.java create mode 100644 TD3/src/main/java/fr/miage23/filestore/api/mapper/NodeHtmlMapper.java create mode 100644 TD3/src/main/java/fr/miage23/filestore/api/resources/NodesResource.java create mode 100644 TD3/src/main/java/fr/miage23/filestore/files/FileService.java create mode 100644 TD3/src/main/java/fr/miage23/filestore/files/InMemoryFileServiceBean.java create mode 100644 TD3/src/main/java/fr/miage23/filestore/files/entity/Node.java create mode 100644 TD3/src/main/java/fr/miage23/filestore/files/exceptions/ContentException.java create mode 100644 TD3/src/main/java/fr/miage23/filestore/files/exceptions/NodeAlreadyExistsException.java create mode 100644 TD3/src/main/java/fr/miage23/filestore/files/exceptions/NodeNotEmptyException.java create mode 100644 TD3/src/main/java/fr/miage23/filestore/files/exceptions/NodeNotFoundException.java create mode 100644 TD3/src/main/java/fr/miage23/filestore/files/exceptions/NodeTypeException.java create mode 100644 TD3/src/main/webapp/WEB-INF/web.xml create mode 100644 TD3/src/main/webapp/index.html create mode 100644 TD3/src/site/site.xml create mode 100644 allumer wildfly pour deploy.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60217e8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +target/ +.idea +target diff --git a/TD2/.gitignore b/TD2/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/TD2/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/TD2/pom.xml b/TD2/pom.xml new file mode 100644 index 0000000..ce3e50c --- /dev/null +++ b/TD2/pom.xml @@ -0,0 +1,65 @@ +<?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>fr.ul.miage</groupId> + <artifactId>td2</artifactId> + <version>1.0-SNAPSHOT</version> + <packaging>war</packaging> + + <properties> + <maven.compiler.source>17</maven.compiler.source> + <maven.compiler.target>17</maven.compiler.target> + <maven.compiler.release>17</maven.compiler.release> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.report.sourceEncoding>UTF-8</project.report.sourceEncoding> + <jakartaee-api.version>10.0.0</jakartaee-api.version> + <wildfly.version>29.0.1.Final</wildfly.version> + <compiler-plugin.version>3.11.0</compiler-plugin.version> + <war-plugin.version>3.3.2</war-plugin.version> + <wildfly-plugin.version>4.2.0.Final</wildfly-plugin.version> + </properties> + + <dependencies> + <dependency> + <groupId>jakarta.platform</groupId> + <artifactId>jakarta.jakartaee-api</artifactId> + <version>${jakartaee-api.version}</version> + <scope>provided</scope> + </dependency> + </dependencies> + + <build> + <finalName>filestore</finalName> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>${compiler-plugin.version}</version> + </plugin> + <plugin> + <artifactId>maven-war-plugin</artifactId> + <version>${war-plugin.version}</version> + <configuration> + <failOnMissingWebXml>false</failOnMissingWebXml> + </configuration> + </plugin> + + <!-- Execute 'mvn clean package wildfly:dev' to run the application. --> + <plugin> + <groupId>org.wildfly.plugins</groupId> + <artifactId>wildfly-maven-plugin</artifactId> + <version>${wildfly-plugin.version}</version> + <configuration> + <version>${wildfly.version}</version> + <server-config>standalone-full.xml</server-config> + <jbossHome>C:\Users\LB-C\Bureau\Logiciels\wildfly-29.0.1.Final</jbossHome> + </configuration> + </plugin> + </plugins> + </build> + + +</project> \ No newline at end of file diff --git a/TD2/src/main/java/fr/ul/miage/td2/FilestoreAPI.java b/TD2/src/main/java/fr/ul/miage/td2/FilestoreAPI.java new file mode 100644 index 0000000..d91423f --- /dev/null +++ b/TD2/src/main/java/fr/ul/miage/td2/FilestoreAPI.java @@ -0,0 +1,9 @@ +package fr.ul.miage.td2; + +import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.core.Application; + +@ApplicationPath("api") +public class FilestoreAPI extends Application { +} + diff --git a/TD2/src/main/java/fr/ul/miage/td2/HelloWorldResource.java b/TD2/src/main/java/fr/ul/miage/td2/HelloWorldResource.java new file mode 100644 index 0000000..49fe4e3 --- /dev/null +++ b/TD2/src/main/java/fr/ul/miage/td2/HelloWorldResource.java @@ -0,0 +1,18 @@ +package fr.ul.miage.td2; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; + +@Path("hello") // "localhost:8080/filestore/api/hello" +public class HelloWorldResource { + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "Hello World (resource)"; + } + +} + diff --git a/TD2/src/main/java/fr/ul/miage/td2/HelloWorldServlet.java b/TD2/src/main/java/fr/ul/miage/td2/HelloWorldServlet.java new file mode 100644 index 0000000..1e49bc7 --- /dev/null +++ b/TD2/src/main/java/fr/ul/miage/td2/HelloWorldServlet.java @@ -0,0 +1,19 @@ +package fr.ul.miage.td2; + +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; + +@WebServlet(name="HelloWorld", urlPatterns = "/hello") +public class HelloWorldServlet extends HttpServlet { + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.getWriter().println("Hello World (servlet)"); + } + +} + diff --git a/TD2/src/main/webapp/WEB-INF/web.xml b/TD2/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..16c84e2 --- /dev/null +++ b/TD2/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd" + version="6.0"> + <!-- + <servlet> + <servlet-name>HelloWorld</servlet-name> + <servlet-class>fr.ul.miage.td2.HelloWorldServlet</servlet-class> + </servlet> + + <servlet-mapping> + <servlet-name>HelloWorld</servlet-name> + <url-pattern>/hello</url-pattern> + </servlet-mapping> --> +</web-app> diff --git a/TD3/README.md b/TD3/README.md new file mode 100644 index 0000000..7769a1f --- /dev/null +++ b/TD3/README.md @@ -0,0 +1,12 @@ +# Filestore Miage.23 Project + +You can run the application by executing the following command from the directory where this file resides. +Please ensure you have installed a [Java SE 17+ implementation](https://adoptium.net/?variant=openjdk17) appropriate for your Jakarta EE version +and runtime choice. You also need to have a working maven installation. + +``` +./mvn clean package wildfly:dev +``` + +Once the runtime starts, you can access the project at http://localhost:8080/filestore + diff --git a/TD3/TD3.md b/TD3/TD3.md new file mode 100644 index 0000000..c16687e --- /dev/null +++ b/TD3/TD3.md @@ -0,0 +1,10 @@ +# http://localhost:8080/filestore/api/nodes _Quel code d'erreur renvoi cet appel ? _ + +Le code renvoie l'erreur : 404 +En effet on a besoin d'un id + +# _Quelle URL faut-il appeler à la place ? Vous allez alors avoir une nouvelle erreur. +On appelle http://localhost:8080/filestore/api/nodes/root +On obtient l'erreur : Could not find MessageBodyWriter for response object of type: fr.miage23.filestore.files.entity.Node of media type: text/html;charset=UTF-8 +On doit traduire le Node en HTML + diff --git a/TD3/pom.xml b/TD3/pom.xml new file mode 100644 index 0000000..e7ac225 --- /dev/null +++ b/TD3/pom.xml @@ -0,0 +1,81 @@ +<?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>fr.miage23.filestore</groupId> + <artifactId>jayblanc</artifactId> + <version>0.1-SNAPSHOT</version> + <packaging>war</packaging> + + <name>The FileStore Application</name> + <organization> + <name>Miage Nancy</name> + <url>http://www.miage-nancy.fr</url> + </organization> + <developers> + <developer> + <id>jayblanc</id> + <name>Jerome Blanchard</name> + <email>jayblanc@gmail.com</email> + <url>http://wiki.jayblanc.fr</url> + <organization>Equasens</organization> + <organizationUrl>http://www.equasens.fr</organizationUrl> + <roles> + <role>developer</role> + </roles> + <timezone>Europe/Paris</timezone> + </developer> + </developers> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.report.sourceEncoding>UTF-8</project.report.sourceEncoding> + <maven.compiler.release>17</maven.compiler.release> + <jakartaee-api.version>10.0.0</jakartaee-api.version> + <wildfly.version>29.0.1.Final</wildfly.version> + <compiler-plugin.version>3.11.0</compiler-plugin.version> + <war-plugin.version>3.4.0</war-plugin.version> + <wildfly-plugin.version>4.2.0.Final</wildfly-plugin.version> + </properties> + + <dependencies> + <dependency> + <groupId>jakarta.platform</groupId> + <artifactId>jakarta.jakartaee-api</artifactId> + <version>${jakartaee-api.version}</version> + <scope>provided</scope> + </dependency> + </dependencies> + + <build> + <finalName>filestore</finalName> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>${compiler-plugin.version}</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-war-plugin</artifactId> + <version>${war-plugin.version}</version> + <configuration> + <failOnMissingWebXml>false</failOnMissingWebXml> + </configuration> + </plugin> + + <!-- Execute 'mvn clean package wildfly:dev' to run the application. --> + <plugin> + <groupId>org.wildfly.plugins</groupId> + <artifactId>wildfly-maven-plugin</artifactId> + <version>${wildfly-plugin.version}</version> + <configuration> + <version>${wildfly.version}</version> + <server-config>standalone-full.xml</server-config> + <jbossHome>C:\Users\LB-C\Bureau\Logiciels\wildfly-29.0.1.Final</jbossHome> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/TD3/src/main/java/fr/miage23/filestore/api/FilestoreApplication.java b/TD3/src/main/java/fr/miage23/filestore/api/FilestoreApplication.java new file mode 100644 index 0000000..a2c2b00 --- /dev/null +++ b/TD3/src/main/java/fr/miage23/filestore/api/FilestoreApplication.java @@ -0,0 +1,8 @@ +package fr.miage23.filestore.api; + +import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.core.Application; + +@ApplicationPath("api") +public class FilestoreApplication extends Application { +} diff --git a/TD3/src/main/java/fr/miage23/filestore/api/dto/Hello.java b/TD3/src/main/java/fr/miage23/filestore/api/dto/Hello.java new file mode 100644 index 0000000..3ed5044 --- /dev/null +++ b/TD3/src/main/java/fr/miage23/filestore/api/dto/Hello.java @@ -0,0 +1,14 @@ +package fr.miage23.filestore.api.dto; + +public class Hello { + + private String name; + + public Hello(String name) { + this.name = name; + } + + public String getHello(){ + return name; + } +} \ No newline at end of file diff --git a/TD3/src/main/java/fr/miage23/filestore/api/exceptions/NodeNotFoundExceptionMapper.java b/TD3/src/main/java/fr/miage23/filestore/api/exceptions/NodeNotFoundExceptionMapper.java new file mode 100644 index 0000000..09ca011 --- /dev/null +++ b/TD3/src/main/java/fr/miage23/filestore/api/exceptions/NodeNotFoundExceptionMapper.java @@ -0,0 +1,16 @@ +package fr.miage23.filestore.api.exceptions; + +import fr.miage23.filestore.files.exceptions.NodeNotFoundException; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import jakarta.ws.rs.ext.Provider; + +@Provider +public class NodeNotFoundExceptionMapper implements ExceptionMapper<NodeNotFoundException> { + + @Override + public Response toResponse(NodeNotFoundException e) { + return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build(); + } +} + diff --git a/TD3/src/main/java/fr/miage23/filestore/api/mapper/NodeHtmlMapper.java b/TD3/src/main/java/fr/miage23/filestore/api/mapper/NodeHtmlMapper.java new file mode 100644 index 0000000..14655ad --- /dev/null +++ b/TD3/src/main/java/fr/miage23/filestore/api/mapper/NodeHtmlMapper.java @@ -0,0 +1,46 @@ +package fr.miage23.filestore.api.mapper; + +import fr.miage23.filestore.files.entity.Node; + +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.ext.MessageBodyWriter; +import jakarta.ws.rs.ext.Provider; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + + +@Provider +@Produces(MediaType.TEXT_HTML) +public class NodeHtmlMapper implements MessageBodyWriter<Node> { + + + @Override + public boolean isWriteable(Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) { + return true; + } + + @Override + public void writeTo(Node node, Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> multivaluedMap, OutputStream outputStream) throws IOException, WebApplicationException { + Writer writer = new PrintWriter(outputStream); + writer.write("<html><head><title>Filestore</title></head>"); + writer.write("<body><h2>" + node.getName() + "</h2>"); + writer.write("<ul><li>id: " + node.getId() + "</li>"); + writer.write("<li>type: " + node.getType() + "</li>"); + writer.write("<li>size: " + node.getSize() + "</li>"); + writer.write("<li>creation: " + node.getCreation() + "</li>"); + writer.write("<li>modification: " + node.getModification() + "</li>"); + writer.write("</ul></body>"); + writer.flush(); + writer.close(); + } +} + + diff --git a/TD3/src/main/java/fr/miage23/filestore/api/resources/NodesResource.java b/TD3/src/main/java/fr/miage23/filestore/api/resources/NodesResource.java new file mode 100644 index 0000000..873d11c --- /dev/null +++ b/TD3/src/main/java/fr/miage23/filestore/api/resources/NodesResource.java @@ -0,0 +1,62 @@ +package fr.miage23.filestore.api.resources; + +import fr.miage23.filestore.files.FileService; +import fr.miage23.filestore.files.entity.Node; +import fr.miage23.filestore.files.InMemoryFileServiceBean; +import fr.miage23.filestore.files.exceptions.NodeAlreadyExistsException; +import fr.miage23.filestore.files.exceptions.NodeNotFoundException; + +import fr.miage23.filestore.files.exceptions.NodeTypeException; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.UriInfo; + +import java.net.URI; +import java.util.logging.Level; +import java.util.logging.Logger; + +@Path("nodes") +public class NodesResource { + + private FileService service = InMemoryFileServiceBean.getInstance(); + private static final Logger LOGGER = Logger.getLogger(NodesResource.class.getName()); + @Context + UriInfo uriInfo; // Injectez l'objet UriInfo pour accéder aux informations d'URI. + + @GET + public Response redirectToDefaultNode() { + String defaultNodeUrl = uriInfo.getBaseUriBuilder().path("nodes/root").build().toString(); + return Response.seeOther(URI.create(defaultNodeUrl)).build(); + } + + @GET + @Path("{id}") + @Produces({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON}) + public Node getNode(@PathParam("id") String id) throws NodeNotFoundException { + LOGGER.log(Level.INFO, "GET /api/nodes/" + id); + return service.get(id); + } + + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public Response createNode(@FormParam("id") String id, @FormParam("name") String name, @Context UriInfo uriInfo) throws NodeNotFoundException, NodeTypeException, NodeAlreadyExistsException { + LOGGER.log(Level.INFO, "POST /api/nodes/" + id); + String newid = service.add(id, name); + return Response.created(uriInfo.getBaseUriBuilder().path(NodesResource.class).path(newid).build()).entity(newid).build(); + } + + @POST + @Path("{id}") + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public Response createNodeWithPath(@PathParam("id") String id, @FormParam("name") String name, @Context UriInfo uriInfo) throws NodeNotFoundException, NodeTypeException, NodeAlreadyExistsException { + LOGGER.log(Level.INFO, "POST /api/nodes/" + id); + String newid = service.add(id, name); + return Response.created(uriInfo.getBaseUriBuilder().path(NodesResource.class).path(newid).build()).entity(newid).build(); + } + + + +} + diff --git a/TD3/src/main/java/fr/miage23/filestore/files/FileService.java b/TD3/src/main/java/fr/miage23/filestore/files/FileService.java new file mode 100644 index 0000000..cd63678 --- /dev/null +++ b/TD3/src/main/java/fr/miage23/filestore/files/FileService.java @@ -0,0 +1,27 @@ +package fr.miage23.filestore.files; + +import fr.miage23.filestore.files.entity.Node; +import fr.miage23.filestore.files.exceptions.*; + +import java.io.InputStream; +import java.util.List; + +public interface FileService { + + String ROOT_NODE_ID = "root"; + String TREE_NODE_MIMETYPE = "application/fs-folder"; + + List<Node> list(String id) throws NodeNotFoundException; + + Node get(String id) throws NodeNotFoundException; + + InputStream getContent(String id) throws NodeNotFoundException, NodeTypeException, ContentException; + + String add(String parent, String name) throws NodeNotFoundException, NodeAlreadyExistsException, NodeTypeException; + + String add(String parent, String name, InputStream content) throws NodeNotFoundException, NodeAlreadyExistsException, NodeTypeException, ContentException; + + void remove(String parent, String name) throws NodeNotFoundException, NodeNotEmptyException, NodeTypeException; + + +} diff --git a/TD3/src/main/java/fr/miage23/filestore/files/InMemoryFileServiceBean.java b/TD3/src/main/java/fr/miage23/filestore/files/InMemoryFileServiceBean.java new file mode 100644 index 0000000..1882b32 --- /dev/null +++ b/TD3/src/main/java/fr/miage23/filestore/files/InMemoryFileServiceBean.java @@ -0,0 +1,147 @@ +package fr.miage23.filestore.files; + +import fr.miage23.filestore.files.entity.Node; +import fr.miage23.filestore.files.exceptions.*; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +public class InMemoryFileServiceBean implements FileService { + + private static final Logger LOGGER = Logger.getLogger(InMemoryFileServiceBean.class.getName()); + + private static Map<String, Node> nodes; + private static Map<String, byte[]> contents; + + private static final class InstanceHolder { + private static final FileService instance = new InMemoryFileServiceBean(); + } + + public static FileService getInstance(){ + return InstanceHolder.instance; + } + + private InMemoryFileServiceBean() { + LOGGER.log(Level.INFO, "Instantiating file service bean"); + contents = new HashMap<>(); + nodes = new ConcurrentHashMap<>(); + Node root = new Node(Node.Type.TREE, "", ROOT_NODE_ID, "root"); + nodes.put(root.getId(), root); + } + + @Override + public List<Node> list(String parent) throws NodeNotFoundException { + String pid = (parent == null || parent.isEmpty())? ROOT_NODE_ID:parent; + LOGGER.log(Level.INFO, "Listing nodes for parent: " + pid); + if (!nodes.containsKey(pid)) { + throw new NodeNotFoundException("unable to find a node with id " + pid + " in the storage"); + } + return nodes.values().stream().filter(n -> n.getParent().equals(pid)).collect(Collectors.toList()); + } + + @Override + public Node get(String id) throws NodeNotFoundException { + LOGGER.log(Level.INFO, "Getting node with id: " + id); + if (!nodes.containsKey(id)) { + throw new NodeNotFoundException("unable to find a node with id " + id + " in the storage"); + } + return nodes.get(id); + } + + @Override + public InputStream getContent(String id) throws NodeNotFoundException, NodeTypeException, ContentException { + LOGGER.log(Level.INFO, "Getting content for node with id: " + id); + if (!nodes.containsKey(id)) { + throw new NodeNotFoundException("unable to find a node with id " + id + " in the storage"); + } + Node node = nodes.get(id); + if (!node.getType().equals(Node.Type.BLOB)) { + throw new NodeTypeException("only node of type BLOB have content"); + } + if (!contents.containsKey(node.getContent())) { + throw new ContentException("unable to find node content with id: " + node.getContent() + " in storage"); + } + return new ByteArrayInputStream(contents.get(node.getContent())); + } + + @Override + public String add(String parent, String name) throws NodeNotFoundException, NodeAlreadyExistsException, NodeTypeException { + String pid = (parent == null || parent.isEmpty())? ROOT_NODE_ID:parent; + LOGGER.log(Level.INFO, "Adding TREE node with name: " + name + " for parent with id: " + pid); + if (!nodes.containsKey(pid)) { + throw new NodeNotFoundException("Unable to find a node with id: " + pid); + } + Node pnode = nodes.get(pid); + if (!pnode.getType().equals(Node.Type.TREE)) { + throw new NodeTypeException("Parent must be a node of type TREE"); + } + if (nodes.values().stream().filter(n -> n.getParent().equals(pid)).anyMatch(n -> n.getName().equals(name))) { + throw new NodeAlreadyExistsException("A node with name: " + name + " already exists in tree with id: " + pid); + } + Node node = new Node(Node.Type.TREE, pid, UUID.randomUUID().toString(), name); + nodes.put(node.getId(), node); + pnode.setSize(pnode.getSize()+1); + return node.getId(); + } + + @Override + public String add(String parent, String name, InputStream content) throws NodeNotFoundException, NodeAlreadyExistsException, NodeTypeException, ContentException { + String pid = (parent == null || parent.isEmpty())? ROOT_NODE_ID:parent; + LOGGER.log(Level.INFO, "Adding BLOB node with name: " + name + " for parent with id: " + pid); + if (!nodes.containsKey(pid)) { + throw new NodeNotFoundException("Unable to find a parent node with id: " + pid); + } + Node pnode = nodes.get(pid); + if (!pnode.getType().equals(Node.Type.TREE)) { + throw new NodeTypeException("Parent must be a node of type TREE"); + } + if (nodes.values().stream().filter(n -> n.getParent().equals(pid)).anyMatch(n -> n.getName().equals(name))) { + throw new NodeAlreadyExistsException("A node with name: " + name + " already exists in tree with id: " + pid); + } + String cid = UUID.randomUUID().toString(); + try { + contents.put(cid, content.readAllBytes()); + Node node = new Node(Node.Type.BLOB, pid, UUID.randomUUID().toString(), name); + node.setContent(cid); + node.setSize(contents.get(cid).length); + node.setMimetype("application/octet-stream"); + nodes.put(node.getId(), node); + pnode.setSize(pnode.getSize()+1); + return node.getId(); + } catch (IOException e) { + throw new ContentException("unable to read file content", e); + } + } + + @Override + public void remove(String parent, String name) throws NodeNotFoundException, NodeNotEmptyException, NodeTypeException { + String pid = (parent == null || parent.isEmpty())? ROOT_NODE_ID:parent; + LOGGER.log(Level.FINE, "Remove node with name: " + name + " and parent: " + pid); + if (!nodes.containsKey(pid)) { + throw new NodeNotFoundException("Unable to find a parent node with id: " + pid); + } + Node pnode = nodes.get(pid); + if (!pnode.getType().equals(Node.Type.TREE)) { + throw new NodeTypeException("Parent must be a node of type TREE"); + } + Optional<Node> node = nodes.values().stream().filter(n -> n.getParent().equals(pid)).filter(n -> n.getName().equals(name)).findAny(); + if (node.isEmpty()) { + throw new NodeNotFoundException("A node with name: " + name + " does not exists in tree with id: " + pid); + } + if (node.get().getType().equals(Node.Type.TREE) && nodes.values().stream().anyMatch(n -> n.getParent().equals(node.get().getId()))) { + throw new NodeNotEmptyException("The node with name: " + name + " is not empty"); + } + if (node.get().getType().equals(Node.Type.BLOB)) { + contents.remove(node.get().getContent()); + } + nodes.remove(node.get().getId()); + pnode.setSize(pnode.getSize()-1); + } + +} diff --git a/TD3/src/main/java/fr/miage23/filestore/files/entity/Node.java b/TD3/src/main/java/fr/miage23/filestore/files/entity/Node.java new file mode 100644 index 0000000..d52979d --- /dev/null +++ b/TD3/src/main/java/fr/miage23/filestore/files/entity/Node.java @@ -0,0 +1,194 @@ +package fr.miage23.filestore.files.entity; + +import fr.miage23.filestore.files.FileService; + +import java.io.Serializable; +import java.util.Comparator; +import java.util.Objects; +import java.util.UUID; + +public class Node implements Comparable<Node>, Serializable { + + private Type type; + private String id; + private long version; + private String parent; + private String name; + private String mimetype; + private long size; + private long creation; + private long modification; + private String content; + + public Node() { + this.creation = this.modification = System.currentTimeMillis(); + this.size = 0; + } + + public Node(Type type, String parent, String id, String name) { + this(); + this.parent = parent; + this.type = type; + this.id = id; + this.name = name; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public long getVersion() { + return version; + } + + public void setVersion(long version) { + this.version = version; + } + + public String getParent() { + return parent; + } + + public void setParent(String parent) { + this.parent = parent; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getMimetype() { + return mimetype; + } + + public void setMimetype(String mimetype) { + this.mimetype = mimetype; + } + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } + + public long getCreation() { + return creation; + } + + public void setCreation(long creation) { + this.creation = creation; + } + + public long getModification() { + return modification; + } + + public void setModification(long modification) { + this.modification = modification; + } + + public boolean isRoot() { + return this.id.equals(FileService.ROOT_NODE_ID); + } + + public boolean isFolder() { + return this.type.equals(Type.TREE); + } + + public enum Type { + TREE, + BLOB + } + + @Override + public int compareTo(Node o) { + if (this.getType().equals(o.getType())) { + return this.getName().compareTo(o.getName()); + } else if (this.getType().equals(Type.TREE)){ + return 1; + } else { + return -1; + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Node node = (Node) o; + return creation == node.creation && modification == node.modification && type == node.type && Objects.equals(id, node.id) && Objects.equals(name, node.name) && Objects.equals(content, node.content) && Objects.equals(mimetype, node.mimetype); + } + + @Override + public int hashCode() { + return Objects.hash(type, id, name, content, mimetype, creation, modification); + } + + @Override + public String toString() { + return "Node{" + + "type=" + type + + ", id='" + id + '\'' + + ", version=" + version + + ", parent='" + parent + '\'' + + ", name='" + name + '\'' + + ", mimetype='" + mimetype + '\'' + + ", size=" + size + + ", creation=" + creation + + ", modification=" + modification + + ", content='" + content + '\'' + + '}'; + } + + public static class NameComparatorAsc implements Comparator<Node> { + @Override + public int compare(Node o1, Node o2) { + if ( o1.isFolder() && !o2.isFolder() ) { + return -1; + } + if ( !o1.isFolder() && o2.isFolder() ) { + return 1; + } + return o1.getName().compareTo(o2.getName()); + } + } + + public static class NameComparatorDesc implements Comparator<Node> { + @Override + public int compare(Node o1, Node o2) { + if ( o1.isFolder() && !o2.isFolder() ) { + return -1; + } + if ( !o1.isFolder() && o2.isFolder() ) { + return 1; + } + return o2.getName().compareTo(o1.getName()); + } + } +} \ No newline at end of file diff --git a/TD3/src/main/java/fr/miage23/filestore/files/exceptions/ContentException.java b/TD3/src/main/java/fr/miage23/filestore/files/exceptions/ContentException.java new file mode 100644 index 0000000..3a4e0fa --- /dev/null +++ b/TD3/src/main/java/fr/miage23/filestore/files/exceptions/ContentException.java @@ -0,0 +1,11 @@ +package fr.miage23.filestore.files.exceptions; + +public class ContentException extends Exception { + + public ContentException(String message) { + super(message); + } + public ContentException(String message, Throwable e) { + super(message, e); + } +} diff --git a/TD3/src/main/java/fr/miage23/filestore/files/exceptions/NodeAlreadyExistsException.java b/TD3/src/main/java/fr/miage23/filestore/files/exceptions/NodeAlreadyExistsException.java new file mode 100644 index 0000000..529f709 --- /dev/null +++ b/TD3/src/main/java/fr/miage23/filestore/files/exceptions/NodeAlreadyExistsException.java @@ -0,0 +1,7 @@ +package fr.miage23.filestore.files.exceptions; + +public class NodeAlreadyExistsException extends Exception { + public NodeAlreadyExistsException(String message) { + super(message); + } +} diff --git a/TD3/src/main/java/fr/miage23/filestore/files/exceptions/NodeNotEmptyException.java b/TD3/src/main/java/fr/miage23/filestore/files/exceptions/NodeNotEmptyException.java new file mode 100644 index 0000000..1e97d12 --- /dev/null +++ b/TD3/src/main/java/fr/miage23/filestore/files/exceptions/NodeNotEmptyException.java @@ -0,0 +1,7 @@ +package fr.miage23.filestore.files.exceptions; + +public class NodeNotEmptyException extends Exception { + public NodeNotEmptyException(String message) { + super(message); + } +} diff --git a/TD3/src/main/java/fr/miage23/filestore/files/exceptions/NodeNotFoundException.java b/TD3/src/main/java/fr/miage23/filestore/files/exceptions/NodeNotFoundException.java new file mode 100644 index 0000000..0995a3a --- /dev/null +++ b/TD3/src/main/java/fr/miage23/filestore/files/exceptions/NodeNotFoundException.java @@ -0,0 +1,11 @@ +package fr.miage23.filestore.files.exceptions; + +public class NodeNotFoundException extends Exception { + public NodeNotFoundException(String message) { + super(message); + } + + public NodeNotFoundException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/TD3/src/main/java/fr/miage23/filestore/files/exceptions/NodeTypeException.java b/TD3/src/main/java/fr/miage23/filestore/files/exceptions/NodeTypeException.java new file mode 100644 index 0000000..3a845de --- /dev/null +++ b/TD3/src/main/java/fr/miage23/filestore/files/exceptions/NodeTypeException.java @@ -0,0 +1,7 @@ +package fr.miage23.filestore.files.exceptions; + +public class NodeTypeException extends Exception { + public NodeTypeException(String message) { + super(message); + } +} diff --git a/TD3/src/main/webapp/WEB-INF/web.xml b/TD3/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..d15a96f --- /dev/null +++ b/TD3/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd" + version="6.0"> + + +</web-app> \ No newline at end of file diff --git a/TD3/src/main/webapp/index.html b/TD3/src/main/webapp/index.html new file mode 100644 index 0000000..3d75f92 --- /dev/null +++ b/TD3/src/main/webapp/index.html @@ -0,0 +1,8 @@ +<html> +<head> +<title>Welcome to Filestore!</title> +</head> +<body> + <h2>Welcome!</h2> +</body> +</html> \ No newline at end of file diff --git a/TD3/src/site/site.xml b/TD3/src/site/site.xml new file mode 100644 index 0000000..1285a50 --- /dev/null +++ b/TD3/src/site/site.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<project name="Maven" xmlns="http://maven.apache.org/DECORATION/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/DECORATION/1.0.0 http://maven.apache.org/xsd/decoration-1.0.0.xsd"> + <bannerLeft> + <name>Miage FileStore project</name> + <src>http://maven.apache.org/images/apache-maven-project.png</src> + <href>http://maven.apache.org/</href> + </bannerLeft> + <bannerRight> + <src>http://maven.apache.org/images/maven-small.gif</src> + </bannerRight> + <body> + <links> + <item name="Apache" href="http://www.apache.org/" /> + <item name="Maven 1.0" href="http://maven.apache.org/"/> + <item name="Maven 2" href="http://maven.apache.org/maven2/"/> + </links> + <menu name="Maven 2.0"> + <item name="Introduction" href="intro.html"/> + </menu> + </body> +</project> diff --git a/allumer wildfly pour deploy.txt b/allumer wildfly pour deploy.txt new file mode 100644 index 0000000..f8f9290 --- /dev/null +++ b/allumer wildfly pour deploy.txt @@ -0,0 +1 @@ +PS C:\Users\LB-C\Bureau\Logiciels\wildfly-29.0.1.Final\bin> .\standalone.bat -- GitLab