[DEV] add other common elements

This commit is contained in:
Edouard DUPIN 2022-12-13 22:37:17 +01:00
parent 044889129a
commit f4ec9e8d82
14 changed files with 631 additions and 291 deletions

View File

@ -19,6 +19,7 @@ Read instruction for tocken in ~/.m2/setting.xml
release:
export PATH=/usr/lib/jvm/java-18-openjdk/bin:$PATH
mvn install
mvn deploy

View File

@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>kangaroo-and-rabbit</groupId>
<artifactId>archidata</artifactId>
<version>0.1.2</version>
<version>0.1.3</version>
<properties>
<jaxrs.version>2.1</jaxrs.version>
<jersey.version>2.32</jersey.version>

View File

@ -4,7 +4,7 @@ import org.kar.archidata.db.DBConfig;
import org.kar.archidata.util.ConfigBaseVariable;
public class GlobalConfiguration {
public static DBConfig dbConfig = null;;
public static DBConfig dbConfig = null;
static {
dbConfig = new DBConfig(ConfigBaseVariable.getDBHost(),

View File

@ -520,9 +520,42 @@ public class SqlWrapper {
}
}
static void addElement(PreparedStatement ps, Object value, int iii) throws Exception {
if (value.getClass() == Long.class) {
ps.setLong(iii, (Long)value);
} else if (value.getClass() == Integer.class) {
ps.setInt(iii, (Integer)value);
} else if (value.getClass() == String.class) {
ps.setString(iii, (String)value);
} else if (value.getClass() == Short.class) {
ps.setShort(iii, (Short)value);
} else if (value.getClass() == Byte.class) {
ps.setByte(iii, (Byte)value);
} else if (value.getClass() == Float.class) {
ps.setFloat(iii, (Float)value);
} else if (value.getClass() == Double.class) {
ps.setDouble(iii, (Double)value);
} else if (value.getClass() == Boolean.class) {
ps.setBoolean(iii, (Boolean)value);
} else if (value.getClass() == Boolean.class) {
ps.setBoolean(iii, (Boolean)value);
} else if (value.getClass() == Timestamp.class) {
ps.setTimestamp(iii, (Timestamp)value);
} else if (value.getClass() == Date.class) {
ps.setDate(iii, (Date)value);
} else {
throw new Exception("Not manage type ==> need to add it ...");
}
}
public static <T> T getWith(Class<T> clazz, String key, String value) throws Exception {
//public static NodeSmall createNode(String typeInNode, String name, String description, Long parentId) {
return getWhere(clazz, key, "=", value);
}
public static <T> T getWhere(Class<T> clazz, String key, String operator, Object value ) throws Exception {
return getWhere(clazz, key, operator, value, null, null, null);
}
public static <T> T getWhere(Class<T> clazz, String key, String operator, Object value, String key2, String operator2, Object value2 ) throws Exception {
DBEntry entry = new DBEntry(GlobalConfiguration.dbConfig);
T out = null;
// real add in the BDD:
@ -535,13 +568,8 @@ public class SqlWrapper {
//query.append(" SET ");
boolean firstField = true;
Field primaryKeyField = null;
int count = 0;
for (Field elem : clazz.getFields()) {
boolean primaryKey = elem.getDeclaredAnnotationsByType(SQLPrimaryKey.class).length != 0;
if (primaryKey) {
primaryKeyField = elem;
}
ModelLink linkGeneric = getLinkMode(elem);
if (linkGeneric != ModelLink.NONE) {
continue;
@ -564,17 +592,28 @@ public class SqlWrapper {
query.append(" ");
query.append(tableName);
query.append(".");
query.append(name);
}
query.append("\n FROM `");
query.append(" FROM `");
query.append(tableName);
query.append("` ");
query.append("\n WHERE ");
query.append(" WHERE ");
query.append(tableName);
query.append(".");
query.append(key);
query.append(" = ?");
query.append("\n LIMIT 1 ");
query.append(" ");
query.append(operator);
query.append(" ?");
if (key2 != null) {
query.append(" AND ");
query.append(tableName);
query.append(".");
query.append(key2);
query.append(" ");
query.append(operator2);
query.append(" ?");
}
/*
query.append(" AND ");
query.append(tableName);
@ -585,7 +624,10 @@ public class SqlWrapper {
// prepare the request:
PreparedStatement ps = entry.connection.prepareStatement(query.toString(), Statement.RETURN_GENERATED_KEYS);
int iii = 1;
ps.setString(iii++, value);
addElement(ps, value, iii++);
if (key2 != null) {
addElement(ps, value2, iii++);
}
// execute the request
ResultSet rs = ps.executeQuery();
while (rs.next()) {
@ -621,11 +663,9 @@ public class SqlWrapper {
entry = null;
return out;
}
public static <T> T getWhere(Class<T> clazz, String key, String operator, Object value ) throws Exception {
public static <T> List<T> getsWhere(Class<T> clazz, String key, String operator, Object value ) throws Exception {
DBEntry entry = new DBEntry(GlobalConfiguration.dbConfig);
T out = null;
List<T> outs = new ArrayList<>();
// real add in the BDD:
try {
String tableName = getTableName(clazz);
@ -683,31 +723,7 @@ public class SqlWrapper {
// prepare the request:
PreparedStatement ps = entry.connection.prepareStatement(query.toString(), Statement.RETURN_GENERATED_KEYS);
int iii = 1;
if (value.getClass() == Long.class) {
ps.setLong(iii++, (Long)value);
} else if (value.getClass() == Integer.class) {
ps.setInt(iii++, (Integer)value);
} else if (value.getClass() == String.class) {
ps.setString(iii++, (String)value);
} else if (value.getClass() == Short.class) {
ps.setShort(iii++, (Short)value);
} else if (value.getClass() == Byte.class) {
ps.setByte(iii++, (Byte)value);
} else if (value.getClass() == Float.class) {
ps.setFloat(iii++, (Float)value);
} else if (value.getClass() == Double.class) {
ps.setDouble(iii++, (Double)value);
} else if (value.getClass() == Boolean.class) {
ps.setBoolean(iii++, (Boolean)value);
} else if (value.getClass() == Boolean.class) {
ps.setBoolean(iii++, (Boolean)value);
} else if (value.getClass() == Timestamp.class) {
ps.setTimestamp(iii++, (Timestamp)value);
} else if (value.getClass() == Date.class) {
ps.setDate(iii++, (Date)value);
} else {
throw new Exception("Not manage type ==> need to add it ...");
}
addElement(ps, value, iii++);
// execute the request
ResultSet rs = ps.executeQuery();
while (rs.next()) {
@ -733,7 +749,8 @@ public class SqlWrapper {
setValueFromDb(elem.getType(), data, count, elem, rs);
count++;
}
out = (T)data;
T out = (T)data;
outs.add(out);
}
} catch (SQLException ex) {
@ -741,7 +758,7 @@ public class SqlWrapper {
}
entry.disconnect();
entry = null;
return out;
return outs;
}
public static <T> T get(Class<T> clazz, long id) throws Exception {
@ -1021,6 +1038,22 @@ public class SqlWrapper {
entry.disconnect();
}
}
public static void unsetDelete(Class<?> clazz, long id) throws Exception {
String tableName = getTableName(clazz);
DBEntry entry = new DBEntry(GlobalConfiguration.dbConfig);
String query = "UPDATE `" + tableName + "` SET `modify_date`=now(3), `deleted`=false WHERE `id` = ?";
try {
PreparedStatement ps = entry.connection.prepareStatement(query);
int iii = 1;
ps.setLong(iii++, id);
ps.executeUpdate();
} catch (SQLException ex) {
ex.printStackTrace();
throw new ExceptionDBInterface(500, "SQL error: " + ex.getMessage());
} finally {
entry.disconnect();
}
}
public static String createTable(Class<?> clazz) throws Exception {
String tableName = getTableName(clazz);

View File

@ -6,12 +6,6 @@ import org.kar.archidata.util.JWTWrapper;
public class UpdateJwtPublicKey extends Thread {
boolean kill = false;
public void run() {
try {
Thread.sleep(1000*20, 0);
} catch (InterruptedException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
while (this.kill == false) {
// need to uppgrade when server call us...
try {

View File

@ -13,76 +13,17 @@ public class UserDB {
public static User getUsers(long userId) throws Exception {
return SqlWrapper.get(User.class, userId);
/*
DBEntry entry = new DBEntry(WebLauncher.dbConfig);
String query = "SELECT * FROM user WHERE id = ?";
try {
PreparedStatement ps = entry.connection.prepareStatement(query);
ps.setLong(1, userId);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
User out = new User(rs);
entry.disconnect();
return out;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
entry.disconnect();
return null;
*/
}
public static User getUserOrCreate(long userId, String userLogin) throws Exception {
User user = getUsers(userId);
if (user != null) {
/*
boolean blocked = false;
boolean removed = false;
if (user.email != userOAuth.email || user.login != userOAuth.login || user.blocked != blocked || user.removed != removed) {
updateUsersInfoFromOAuth(userOAuth.id, userOAuth.email, userOAuth.login, blocked, removed);
} else {
updateUsersConnectionTime(userOAuth.id);
}
return getUsers(userOAuth.id);
*/
return user;
}
createUsersInfoFromOAuth(userId, userLogin);
return getUsers(userId);
}
/*
private static void updateUsersConnectionTime(long userId) {
DBEntry entry = new DBEntry(WebLauncher.dbConfig);
String query = "UPDATE `user` SET `lastConnection`=now(3) WHERE `id` = ?";
try {
PreparedStatement ps = entry.connection.prepareStatement(query);
ps.setLong(1, userId);
ps.executeUpdate();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
entry.disconnect();
}
private static void updateUsersInfoFromOAuth(long userId, String email, String login, boolean blocked, boolean removed) {
DBEntry entry = new DBEntry(WebLauncher.dbConfig);
String query = "UPDATE `user` SET `login`=?, `email`=?, `lastConnection`=now(3), `blocked`=?, `removed`=? WHERE id = ?";
try {
PreparedStatement ps = entry.connection.prepareStatement(query);
ps.setString(1, login);
ps.setString(2, email);
ps.setString(3, blocked ? "TRUE" : "FALSE");
ps.setString(4, removed ? "TRUE" : "FALSE");
ps.setLong(5, userId);
ps.executeUpdate();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
entry.disconnect();
}
*/
private static void createUsersInfoFromOAuth(long userId, String login) {
DBEntry entry = new DBEntry(GlobalConfiguration.dbConfig);

View File

@ -0,0 +1,12 @@
package org.kar.archidata.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLForeignKey {
String value();
}

View File

@ -5,7 +5,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@NameBinding

View File

@ -0,0 +1,429 @@
package org.kar.archidata.api;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.filter.GenericContext;
import org.kar.archidata.model.Data;
import org.kar.archidata.SqlWrapper;
import org.kar.archidata.annotation.security.PermitTokenInURI;
import org.kar.archidata.annotation.security.RolesAllowed;
import org.kar.archidata.util.ConfigBaseVariable;
import javax.imageio.ImageIO;
import javax.ws.rs.*;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.StreamingOutput;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
// https://stackoverflow.com/questions/35367113/jersey-webservice-scalable-approach-to-download-file-and-reply-to-client
// https://gist.github.com/aitoroses/4f7a2b197b732a6a691d
@Path("/data")
@Produces({MediaType.APPLICATION_JSON})
public class DataResource {
private final static int CHUNK_SIZE = 1024 * 1024; // 1MB chunks
private final static int CHUNK_SIZE_IN = 50 * 1024 * 1024; // 1MB chunks
/**
* Upload some datas
*/
private static long tmpFolderId = 1;
private static void createFolder(String path) throws IOException {
if (!Files.exists(java.nio.file.Path.of(path))) {
//Log.print("Create folder: " + path);
Files.createDirectories(java.nio.file.Path.of(path));
}
}
public static long getTmpDataId() {
return tmpFolderId++;
}
public static String getTmpFileInData(long tmpFolderId) {
String filePath = ConfigBaseVariable.getTmpDataFolder() + File.separator + tmpFolderId;
try {
createFolder(ConfigBaseVariable.getTmpDataFolder() + File.separator);
} catch (IOException e) {
e.printStackTrace();
}
return filePath;
}
public static String getFileData(long tmpFolderId) {
String filePath = ConfigBaseVariable.getMediaDataFolder() + File.separator + tmpFolderId + File.separator + "data";
try {
createFolder(ConfigBaseVariable.getMediaDataFolder() + File.separator + tmpFolderId + File.separator);
} catch (IOException e) {
e.printStackTrace();
}
return filePath;
}
public static Data getWithSha512(String sha512) {
System.out.println("find sha512 = " + sha512);
try {
return SqlWrapper.getWhere(Data.class, "sha512", "=", sha512);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static Data getWithId(long id) {
System.out.println("find id = " + id);
try {
return SqlWrapper.get(Data.class, id);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static Data createNewData(long tmpUID, String originalFileName, String sha512) throws IOException {
// determine mime type:
Data injectedData = new Data();
String mimeType = "";
String extension = originalFileName.substring(originalFileName.lastIndexOf('.') + 1);
switch (extension.toLowerCase()) {
case "jpg":
case "jpeg":
mimeType = "image/jpeg";
break;
case "png":
mimeType = "image/png";
break;
case "webp":
mimeType = "image/webp";
break;
case "mka":
mimeType = "audio/x-matroska";
break;
case "mkv":
mimeType = "video/x-matroska";
break;
case "webm":
mimeType = "video/webm";
break;
default:
throw new IOException("Can not find the mime type of data input: '" + extension + "'");
}
injectedData.mimeType = mimeType;
injectedData.sha512 = sha512;
String tmpPath = getTmpFileInData(tmpUID);
injectedData.size = Files.size(Paths.get(tmpPath));
try {
injectedData = SqlWrapper.insert(injectedData);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
String mediaPath = getFileData(injectedData.id);
System.out.println("src = " + tmpPath);
System.out.println("dst = " + mediaPath);
Files.move(Paths.get(tmpPath), Paths.get(mediaPath), StandardCopyOption.ATOMIC_MOVE);
System.out.println("Move done");
return injectedData;
}
public static String saveTemporaryFile(InputStream uploadedInputStream, long idData) {
return saveFile(uploadedInputStream, DataResource.getTmpFileInData(idData));
}
public static void removeTemporaryFile(long idData) {
String filepath = DataResource.getTmpFileInData(idData);
if (Files.exists(Paths.get(filepath))) {
try {
Files.delete(Paths.get(filepath));
} catch (IOException e) {
System.out.println("can not delete temporary file : " + Paths.get(filepath));
e.printStackTrace();
}
}
}
// save uploaded file to a defined location on the server
static String saveFile(InputStream uploadedInputStream, String serverLocation) {
String out = "";
try {
OutputStream outpuStream = new FileOutputStream(new File(
serverLocation));
int read = 0;
byte[] bytes = new byte[CHUNK_SIZE_IN];
MessageDigest md = MessageDigest.getInstance("SHA-512");
outpuStream = new FileOutputStream(new File(serverLocation));
while ((read = uploadedInputStream.read(bytes)) != -1) {
//System.out.println("write " + read);
md.update(bytes, 0, read);
outpuStream.write(bytes, 0, read);
}
System.out.println("Flush input stream ... " + serverLocation);
System.out.flush();
outpuStream.flush();
outpuStream.close();
// create the end of sha512
byte[] sha512Digest = md.digest();
// convert in hexadecimal
out = bytesToHex(sha512Digest);
uploadedInputStream.close();
} catch (IOException ex) {
System.out.println("Can not write in temporary file ... ");
ex.printStackTrace();
} catch (NoSuchAlgorithmException ex) {
System.out.println("Can not find sha512 algorithms");
ex.printStackTrace();
}
return out;
}
public static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
public Data getSmall(Long id) {
try {
return SqlWrapper.get(Data.class, id);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
@POST
@Path("/upload/")
@Consumes({MediaType.MULTIPART_FORM_DATA})
@RolesAllowed("ADMIN")
public Response uploadFile(@Context SecurityContext sc, @FormDataParam("file") InputStream fileInputStream, @FormDataParam("file") FormDataContentDisposition fileMetaData) {
GenericContext gc = (GenericContext) sc.getUserPrincipal();
System.out.println("===================================================");
System.out.println("== DATA uploadFile " + (gc==null?"null":gc.user));
System.out.println("===================================================");
//public NodeSmall uploadFile(final FormDataMultiPart form) {
System.out.println("Upload file: ");
String filePath = ConfigBaseVariable.getTmpDataFolder() + File.separator + tmpFolderId++;
try {
createFolder(ConfigBaseVariable.getTmpDataFolder() + File.separator);
} catch (IOException e) {
e.printStackTrace();
}
saveFile(fileInputStream, filePath);
return Response.ok("Data uploaded successfully !!").build();
//return null;
}
@GET
@Path("{id}")
@PermitTokenInURI
@RolesAllowed("USER")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response retriveDataId(@Context SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) String token, @HeaderParam("Range") String range, @PathParam("id") Long id) throws Exception {
GenericContext gc = (GenericContext) sc.getUserPrincipal();
//System.out.println("===================================================");
System.out.println("== DATA retriveDataId ? id=" + id + " user=" + (gc==null?"null":gc.user));
//System.out.println("===================================================");
Data value = getSmall(id);
if (value == null) {
Response.status(404).
entity("media NOT FOUND: " + id).
type("text/plain").
build();
}
return buildStream(ConfigBaseVariable.getMediaDataFolder() + File.separator + id + File.separator + "data", range, value.mimeType);
}
@GET
@Path("thumbnail/{id}")
@RolesAllowed("USER")
@PermitTokenInURI
@Produces(MediaType.APPLICATION_OCTET_STREAM)
//@CacheMaxAge(time = 10, unit = TimeUnit.DAYS)
public Response retriveDataThumbnailId(@Context SecurityContext sc,
@QueryParam(HttpHeaders.AUTHORIZATION) String token,
@HeaderParam("Range") String range,
@PathParam("id") Long id) throws Exception {
GenericContext gc = (GenericContext) sc.getUserPrincipal();
//System.out.println("===================================================");
//System.out.println("== DATA retriveDataThumbnailId ? " + (gc==null?"null":gc.user));
//System.out.println("===================================================");
Data value = getSmall(id);
if (value == null) {
return Response.status(404).
entity("media NOT FOUND: " + id).
type("text/plain").
build();
}
String filePathName = ConfigBaseVariable.getMediaDataFolder() + File.separator + id + File.separator + "data";
if ( value.mimeType.contentEquals("image/jpeg")
|| value.mimeType.contentEquals("image/png")
// || value.mimeType.contentEquals("image/webp")
) {
// reads input image
//System.out.println("Read path: " + filePathName);
File inputFile = new File(filePathName);
if (!inputFile.exists()) {
return Response.status(500).
entity("Internal Error: Media is NOT FOUNDABLE: " + id).
type("text/plain").
build();
}
BufferedImage inputImage = ImageIO.read(inputFile);
int scaledWidth = 250;
int scaledHeight = (int)((float)inputImage.getHeight() / (float)inputImage.getWidth() * (float) scaledWidth);
// creates output image
BufferedImage outputImage = new BufferedImage(scaledWidth,
scaledHeight, inputImage.getType());
// scales the input image to the output image
Graphics2D g2d = outputImage.createGraphics();
g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null);
g2d.dispose();
// create the output stream:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
// TODO: check how to remove buffer file !!! here, it is not needed at all...
ImageIO.write( outputImage, "JPG", baos);
} catch (IOException e) {
e.printStackTrace();
return Response.status(500).
entity("Internal Error: resize fail: " + e.getMessage()).
type("text/plain").
build();
}
byte[] imageData = baos.toByteArray();
//Response.ok(new ByteArrayInputStream(imageData)).build();
Response.ResponseBuilder out = Response.ok(imageData)
.header(HttpHeaders.CONTENT_LENGTH, imageData.length);
out.type("image/jpeg");
// TODO: move this in a decorator !!!
CacheControl cc = new CacheControl();
cc.setMaxAge(3600);
cc.setNoCache(false);
out.cacheControl(cc);
return out.build();
}
return buildStream(filePathName, range, value.mimeType);
}
//@Secured
@GET
@Path("{id}/{name}")
@PermitTokenInURI
@RolesAllowed("USER")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response retriveDataFull(@Context SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) String token, @HeaderParam("Range") String range, @PathParam("id") Long id, @PathParam("name") String name) throws Exception {
GenericContext gc = (GenericContext) sc.getUserPrincipal();
//System.out.println("===================================================");
System.out.println("== DATA retriveDataFull ? id=" + id + " user=" + (gc==null?"null":gc.user));
//System.out.println("===================================================");
Data value = getSmall(id);
if (value == null) {
Response.status(404).
entity("media NOT FOUND: " + id).
type("text/plain").
build();
}
return buildStream(ConfigBaseVariable.getMediaDataFolder() + File.separator + id + File.separator + "data", range, value.mimeType);
}
/**
* Adapted from http://stackoverflow.com/questions/12768812/video-streaming-to-ipad-does-not-work-with-tapestry5/12829541#12829541
*
* @param range range header
* @return Streaming output
* @throws Exception IOException if an error occurs in streaming.
*/
private Response buildStream(final String filename, final String range, String mimeType) throws Exception {
File file = new File(filename);
//System.out.println("request range : " + range);
// range not requested : Firefox does not send range headers
if (range == null) {
final StreamingOutput output = new StreamingOutput() {
@Override
public void write(OutputStream out) {
try (FileInputStream in = new FileInputStream(file)) {
byte[] buf = new byte[1024 * 1024];
int len;
while ((len = in.read(buf)) != -1) {
try {
out.write(buf, 0, len);
out.flush();
//System.out.println("---- wrote " + len + " bytes file ----");
} catch (IOException ex) {
System.out.println("remote close connection");
break;
}
}
} catch (IOException ex) {
throw new InternalServerErrorException(ex);
}
}
};
Response.ResponseBuilder out = Response.ok(output)
.header(HttpHeaders.CONTENT_LENGTH, file.length());
if (mimeType != null) {
out.type(mimeType);
}
return out.build();
}
String[] ranges = range.split("=")[1].split("-");
final long from = Long.parseLong(ranges[0]);
//System.out.println("request range : " + ranges.length);
//Chunk media if the range upper bound is unspecified. Chrome, Opera sends "bytes=0-"
long to = CHUNK_SIZE + from;
if (ranges.length == 1) {
to = file.length() - 1;
} else {
if (to >= file.length()) {
to = (long) (file.length() - 1);
}
}
final String responseRange = String.format("bytes %d-%d/%d", from, to, file.length());
//System.out.println("responseRange : " + responseRange);
final RandomAccessFile raf = new RandomAccessFile(file, "r");
raf.seek(from);
final long len = to - from + 1;
final MediaStreamer streamer = new MediaStreamer(len, raf);
Response.ResponseBuilder out = Response.ok(streamer)
.status(Response.Status.PARTIAL_CONTENT)
.header("Accept-Ranges", "bytes")
.header("Content-Range", responseRange)
.header(HttpHeaders.CONTENT_LENGTH, streamer.getLenth())
.header(HttpHeaders.LAST_MODIFIED, new Date(file.lastModified()));
if (mimeType != null) {
out.type(mimeType);
}
return out.build();
}
public static void undelete(Long id) throws Exception {
SqlWrapper.unsetDelete(Data.class, id);
}
}

View File

@ -0,0 +1,56 @@
package org.kar.archidata.api;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
public class MediaStreamer implements StreamingOutput {
private final int CHUNK_SIZE = 1024 * 1024; // 1MB chunks
final byte[] buf = new byte[CHUNK_SIZE];
private long length;
private RandomAccessFile raf;
public MediaStreamer(long length, RandomAccessFile raf) throws IOException {
//System.out.println("request stream of " + length / 1024 + " data");
if (length<0) {
throw new IOException("Wrong size of the file to stream: " + length);
}
this.length = length;
this.raf = raf;
}
@Override
public void write(OutputStream outputStream) {
try {
while (length != 0) {
int read = raf.read(buf, 0, buf.length > length ? (int) length : buf.length);
try {
outputStream.write(buf, 0, read);
} catch (IOException ex) {
System.out.println("remote close connection");
break;
}
length -= read;
}
} catch (IOException ex) {
throw new InternalServerErrorException(ex);
} catch (WebApplicationException ex) {
throw new InternalServerErrorException(ex);
} finally {
try {
raf.close();
} catch (IOException ex) {
ex.printStackTrace();
throw new InternalServerErrorException(ex);
}
}
}
public long getLenth() {
return length;
}
}

View File

@ -3,30 +3,29 @@ package org.kar.archidata.model;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Data {
public Long id;
public boolean deleted;
import org.kar.archidata.annotation.SQLComment;
import org.kar.archidata.annotation.SQLIfNotExists;
import org.kar.archidata.annotation.SQLLimitSize;
import org.kar.archidata.annotation.SQLNotNull;
import org.kar.archidata.annotation.SQLTableName;
import org.kar.archidata.model.GenericTable;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
@SQLTableName ("data")
@SQLIfNotExists
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
public class Data extends GenericTable {
@SQLNotNull
@SQLLimitSize(128)
@SQLComment("Sha512 of the data")
public String sha512;
@SQLNotNull
@SQLLimitSize(128)
@SQLComment("Mime -type of the media")
public String mimeType;
@SQLNotNull
@SQLComment("Size in Byte of the data")
public Long size;
public Data() {
}
public Data(ResultSet rs) {
int iii = 1;
try {
this.id = rs.getLong(iii++);
this.deleted = rs.getBoolean(iii++);
this.sha512 = rs.getString(iii++);
this.mimeType = rs.getString(iii++);
this.size = rs.getLong(iii++);
if (rs.wasNull()) {
this.size = null;
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}

View File

@ -30,12 +30,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
@SQLTableName ("user")
@SQLIfNotExists
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
public class User {
@SQLAutoIncrement // Add AUTO_INCREMENT modifier
@SQLPrimaryKey // Create a PRIMARY KEY based on this field
@SQLNotNull
@SQLComment("Primary key of the base")
public Long id = null;
public class User extends GenericTable {
@SQLLimitSize(128)
public String login = null;

View File

@ -1,73 +0,0 @@
package org.kar.archidata.model;
/*
CREATE TABLE `user` (
`id` bigint NOT NULL COMMENT 'table ID' AUTO_INCREMENT PRIMARY KEY,
`login` varchar(128) COLLATE 'utf8_general_ci' NOT NULL COMMENT 'login of the user',
`password` varchar(128) COLLATE 'latin1_bin' NOT NULL COMMENT 'password of the user hashed (sha512)',
`email` varchar(512) COLLATE 'utf8_general_ci' NOT NULL COMMENT 'email of the user',
`emailValidate` bigint COMMENT 'date of the email validation',
`newEmail` varchar(512) COLLATE 'utf8_general_ci' COMMENT 'email of the user if he want to change',
`authorisationLevel` enum("REMOVED", "USER", "ADMIN") NOT NULL COMMENT 'user level of authorization'
) AUTO_INCREMENT=10;
*/
import java.sql.ResultSet;
import java.sql.SQLException;
public class UserSmall {
public long id;
public String login;
public String email;
public State authorisationLevel;
public UserSmall() {
}
public UserSmall(long id, String login, String email, State authorisationLevel) {
this.id = id;
this.login = login;
this.email = email;
this.authorisationLevel = authorisationLevel;
}
public UserSmall(ResultSet rs) {
int iii = 1;
try {
this.id = rs.getLong(iii++);
this.login = rs.getString(iii++);
this.email = rs.getString(iii++);
this.authorisationLevel = State.valueOf(rs.getString(iii++));
} catch (SQLException ex) {
ex.printStackTrace();
}
}
/*
public void serialize(ResultSet rs) {
int iii = 1;
try {
this.id = rs.getLong(iii++);
this.login = rs.getString(iii++);
this.password = rs.getString(iii++);
this.email = rs.getString(iii++);
this.emailValidate = rs.getLong(iii++);
this.newEmail = rs.getString(iii++);
this.authorisationLevel = State.valueOf(rs.getString(iii++));
} catch (SQLException ex) {
ex.printStackTrace();
}
}
*/
@Override
public String toString() {
return "UserSmall{" +
"id='" + id + '\'' +
", login='" + login + '\'' +
", email='" + email + '\'' +
", authorisationLevel=" + authorisationLevel +
'}';
}
}

View File

@ -73,43 +73,23 @@ public class DataTools {
}
public static Data getWithSha512(String sha512) {
System.out.println("find sha512 = " + sha512);
DBEntry entry = new DBEntry(GlobalConfiguration.dbConfig);
String query = "SELECT `id`, `deleted`, `sha512`, `mime_type`, `size` FROM `data` WHERE `sha512` = ?";
try {
PreparedStatement ps = entry.connection.prepareStatement(query);
ps.setString(1, sha512);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
Data out = new Data(rs);
entry.disconnect();
return out;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
entry.disconnect();
return null;
try {
return SqlWrapper.getWhere(Data.class, "sha512", "=", sha512);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static Data getWithId(long id) {
DBEntry entry = new DBEntry(GlobalConfiguration.dbConfig);
String query = "SELECT `id`, `deleted`, `sha512`, `mime_type`, `size` FROM `data` WHERE `deleted` = false AND `id` = ?";
try {
PreparedStatement ps = entry.connection.prepareStatement(query);
ps.setLong(1, id);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
Data out = new Data(rs);
entry.disconnect();
return out;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
entry.disconnect();
return null;
try {
return SqlWrapper.getWhere(Data.class, "deleted", "=", false, "id", "=", id);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static Data createNewData(long tmpUID, String originalFileName, String sha512) throws IOException, SQLException {
@ -141,41 +121,20 @@ public class DataTools {
}
String tmpPath = getTmpFileInData(tmpUID);
long fileSize = Files.size(Paths.get(tmpPath));
DBEntry entry = new DBEntry(GlobalConfiguration.dbConfig);
long uniqueSQLID = -1;
Data out = new Data();;
try {
// prepare the request:
String query = "INSERT INTO `data` (`sha512`, `mime_type`, `size`, `original_name`) VALUES (?, ?, ?, ?)";
PreparedStatement ps = entry.connection.prepareStatement(query,
Statement.RETURN_GENERATED_KEYS);
int iii = 1;
ps.setString(iii++, sha512);
ps.setString(iii++, mimeType);
ps.setLong(iii++, fileSize);
ps.setString(iii++, originalFileName);
// execute the request
int affectedRows = ps.executeUpdate();
if (affectedRows == 0) {
throw new SQLException("Creating data failed, no rows affected.");
}
// retreive uid inserted
try (ResultSet generatedKeys = ps.getGeneratedKeys()) {
if (generatedKeys.next()) {
uniqueSQLID = generatedKeys.getLong(1);
} else {
throw new SQLException("Creating user failed, no ID obtained (1).");
}
} catch (Exception ex) {
System.out.println("Can not get the UID key inserted ... ");
ex.printStackTrace();
throw new SQLException("Creating user failed, no ID obtained (2).");
}
out.sha512 = sha512;
out.mimeType = mimeType;
out.size = fileSize;
out = SqlWrapper.insert(out);
} catch (SQLException ex) {
ex.printStackTrace();
}
entry.disconnect();
System.out.println("Add Data raw done. uid data=" + uniqueSQLID);
Data out = getWithId(uniqueSQLID);
return null;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
String mediaPath = getFileData(out.id);
System.out.println("src = " + tmpPath);
@ -183,22 +142,17 @@ public class DataTools {
Files.move(Paths.get(tmpPath), Paths.get(mediaPath), StandardCopyOption.ATOMIC_MOVE);
System.out.println("Move done");
// all is done the file is corectly installed...
// all is done the file is correctly installed...
return out;
}
public static void undelete(Long id) {
DBEntry entry = new DBEntry(GlobalConfiguration.dbConfig);
String query = "UPDATE `data` SET `deleted` = false WHERE `id` = ?";
try {
PreparedStatement ps = entry.connection.prepareStatement(query);
ps.setLong(1, id);
ps.execute();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
entry.disconnect();
try {
SqlWrapper.unsetDelete(Data.class, id);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String saveTemporaryFile(InputStream uploadedInputStream, long idData) {