195 lines
6.2 KiB
Java
195 lines
6.2 KiB
Java
package org.gcube.data.access.storagehub.services.admin;
|
|
|
|
import static org.gcube.data.access.storagehub.Roles.INFRASTRUCTURE_MANAGER_ROLE;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.InputStream;
|
|
import java.io.PrintWriter;
|
|
import java.io.StringReader;
|
|
import java.io.StringWriter;
|
|
|
|
import javax.inject.Inject;
|
|
import javax.jcr.Node;
|
|
import javax.servlet.ServletContext;
|
|
import javax.ws.rs.Consumes;
|
|
import javax.ws.rs.POST;
|
|
import javax.ws.rs.Path;
|
|
import javax.ws.rs.WebApplicationException;
|
|
import javax.ws.rs.core.Context;
|
|
import javax.ws.rs.core.MediaType;
|
|
|
|
import org.apache.cxf.io.ReaderInputStream;
|
|
import org.apache.jackrabbit.api.JackrabbitSession;
|
|
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
|
|
import org.gcube.common.authorization.library.AuthorizedTasks;
|
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
|
import org.gcube.common.storagehub.model.Paths;
|
|
import org.gcube.data.access.storagehub.PathUtil;
|
|
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
|
|
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
|
import org.gcube.data.access.storagehub.exception.MyAuthException;
|
|
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
|
import org.gcube.data.access.storagehub.handlers.items.ItemHandler;
|
|
import org.gcube.data.access.storagehub.handlers.items.builders.FileCreationParameters;
|
|
import org.gcube.data.access.storagehub.handlers.items.builders.ItemsParameterBuilder;
|
|
import org.gcube.data.access.storagehub.scripting.AbstractScript;
|
|
import org.gcube.data.access.storagehub.scripting.ScriptUtil;
|
|
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
|
|
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
|
import org.glassfish.jersey.media.multipart.FormDataParam;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
@Path("admin/script")
|
|
public class ScriptManager {
|
|
|
|
|
|
private static Logger log = LoggerFactory.getLogger(ScriptManager.class);
|
|
|
|
private RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
|
|
|
@Inject
|
|
AccountingHandler accountingHandler;
|
|
|
|
@Context
|
|
ServletContext context;
|
|
|
|
@Inject
|
|
ScriptUtil scriptUtil;
|
|
|
|
@Inject
|
|
ItemHandler itemHandler;
|
|
|
|
@Inject
|
|
PathUtil pathUtil;
|
|
|
|
@POST
|
|
@Path("execute")
|
|
@AuthorizationControl(allowedRoles = {INFRASTRUCTURE_MANAGER_ROLE},exception=MyAuthException.class)
|
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
|
public String run( @FormDataParam("name") String name,
|
|
@FormDataParam("asynch") Boolean asynch,
|
|
@FormDataParam("destinationFolderId") String destinationFolderId,
|
|
@FormDataParam("file") InputStream stream,
|
|
@FormDataParam("file") FormDataContentDisposition fileDetail) {
|
|
try {
|
|
ScriptClassLoader scriptClassLoader = new ScriptClassLoader(Thread.currentThread().getContextClassLoader());
|
|
Class<?> scriptClass = uploadClass(stream, scriptClassLoader, fileDetail.getFileName().replace(".class", ""));
|
|
return run(scriptClass, name, destinationFolderId, asynch!=null? asynch : false);
|
|
}catch(Throwable e) {
|
|
log.error("error executing script {}", name,e);
|
|
throw new WebApplicationException("error loading class",e);
|
|
}
|
|
}
|
|
|
|
|
|
private Class<?> uploadClass(InputStream stream, ScriptClassLoader classLoader, String name) throws Throwable {
|
|
try(ByteArrayOutputStream buffer = new ByteArrayOutputStream()){
|
|
int nRead;
|
|
byte[] data = new byte[1024];
|
|
while ((nRead = stream.read(data, 0, data.length)) != -1)
|
|
buffer.write(data, 0, nRead);
|
|
|
|
buffer.flush();
|
|
byte[] byteArray = buffer.toByteArray();
|
|
return classLoader.findClass(name, byteArray);
|
|
}
|
|
|
|
}
|
|
|
|
private String run(Class<?> clazz, String name, String destinationFolderId, boolean asynch) throws Throwable {
|
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
|
log.info("script {} called by {}", clazz.getSimpleName(), login);
|
|
JackrabbitSession ses = null;
|
|
|
|
try {
|
|
ses = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
|
|
String parentId = destinationFolderId!=null ? destinationFolderId : ses.getNode(pathUtil.getWorkspacePath(login).toPath()).getIdentifier();
|
|
Node parentNode = ses.getNodeByIdentifier(parentId);
|
|
String parentPath = parentNode.getPath();
|
|
|
|
if (AbstractScript.class.isAssignableFrom(clazz)) {
|
|
AbstractScript scriptInstance = (AbstractScript) clazz.newInstance();
|
|
|
|
RealRun realRun = new RealRun(ses, scriptInstance, login, parentId, name);
|
|
if (asynch) {
|
|
new Thread(AuthorizedTasks.bind(realRun)).start();
|
|
}else realRun.run();
|
|
|
|
} else throw new Exception("class "+clazz.getSimpleName()+" not implements AbstractScript");
|
|
|
|
return Paths.append(Paths.getPath(parentPath), name).toPath();
|
|
|
|
}catch (Throwable e) {
|
|
if (ses !=null && ses.isLive())
|
|
ses.logout();
|
|
throw e;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
class RealRun implements Runnable{
|
|
|
|
private JackrabbitSession ses;
|
|
AbstractScript instance;
|
|
String login;
|
|
String parentId;
|
|
String name;
|
|
|
|
public RealRun(JackrabbitSession ses, AbstractScript instance, String login, String parentId, String name) {
|
|
super();
|
|
this.ses = ses;
|
|
this.instance = instance;
|
|
this.login = login;
|
|
this.parentId = parentId;
|
|
this.name = name;
|
|
}
|
|
|
|
|
|
@Override
|
|
public void run() {
|
|
try{
|
|
String result ="";
|
|
try {
|
|
result = instance.run(ses, null, scriptUtil);
|
|
log.info("result is {}",result);
|
|
}catch(Throwable t) {
|
|
StringWriter sw = new StringWriter();
|
|
PrintWriter pw = new PrintWriter(sw, true);
|
|
t.printStackTrace(pw);
|
|
result+= "\n"+sw.toString();
|
|
}
|
|
|
|
try( InputStream stream = new ReaderInputStream(new StringReader(result))){
|
|
ItemsParameterBuilder<FileCreationParameters> builder = FileCreationParameters.builder().name(name).description("result of script execution "+name)
|
|
.stream(stream).on(parentId).with(ses).author(login);
|
|
itemHandler.create(builder.build());
|
|
} catch (Throwable e) {
|
|
log.error("error saving script result {} in the Workspace",name, e);
|
|
}
|
|
|
|
} finally {
|
|
if (ses!=null)
|
|
ses.logout();
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
class ScriptClassLoader extends ClassLoader{
|
|
|
|
public ScriptClassLoader(ClassLoader parent) {
|
|
super(parent);
|
|
}
|
|
|
|
public Class<?> findClass(String name, byte[] b) {
|
|
return defineClass(name, b, 0, b.length);
|
|
}
|
|
}
|
|
|
|
}
|