Implemented Feature #5028 with WebSockets
Workspace enhancements: avoid http timeout during folder compression git-svn-id: http://svn.d4science-ii.research-infrastructures.eu/gcube/trunk/portlets/user/workspace@131598 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
parent
96f7180765
commit
4928d1e554
13
.classpath
13
.classpath
|
@ -6,14 +6,22 @@
|
|||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry including="**/*.java" kind="src" output="src/main/webapp/WEB-INF/classes" path="src/main/resources"/>
|
||||
<classpathentry excluding="**" kind="src" output="target/workspace-6.14.0-SNAPSHOT/WEB-INF/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry including="**/*.java" kind="src" output="target/test-classes" path="src/test/resources"/>
|
||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
|
@ -26,5 +34,6 @@
|
|||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="com.google.gwt.eclipse.core.GWT_CONTAINER"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/WorkspaceTree"/>
|
||||
<classpathentry kind="output" path="target/workspace-6.14.0-SNAPSHOT/WEB-INF/classes"/>
|
||||
</classpath>
|
||||
|
|
1
.project
1
.project
|
@ -55,5 +55,6 @@
|
|||
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
|
||||
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
|
||||
<nature>com.google.gwt.eclipse.core.gwtNature</nature>
|
||||
<nature>com.liferay.ide.core.liferayNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
|
||||
<wb-module deploy-name="workspace-TRUNK-portlet">
|
||||
<wb-module deploy-name="workspace-portlet">
|
||||
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
|
||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/target/generated-sources/gwt"/>
|
||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
|
||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
|
||||
<dependent-module archiveName="workspace-tree-widget-6.14.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/workspace-tree-widget-TRUNK/workspace-tree-widget-TRUNK">
|
||||
<dependent-module archiveName="workspace-tree-widget-6.14.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/WorkspaceTree/WorkspaceTree">
|
||||
<dependency-type>uses</dependency-type>
|
||||
</dependent-module>
|
||||
|
||||
|
|
39
pom.xml
39
pom.xml
|
@ -51,11 +51,11 @@
|
|||
<dependencies>
|
||||
|
||||
<!-- UNCOMMENT THIS TO RUN IN DEVO MODE -->
|
||||
<!-- <dependency> -->
|
||||
<!-- <groupId>xerces</groupId> -->
|
||||
<!-- <artifactId>xerces</artifactId> -->
|
||||
<!-- <version>2.4.0</version> -->
|
||||
<!-- </dependency> -->
|
||||
<!-- <dependency> -->
|
||||
<!-- <groupId>xerces</groupId> -->
|
||||
<!-- <artifactId>xerces</artifactId> -->
|
||||
<!-- <version>2.4.0</version> -->
|
||||
<!-- </dependency> -->
|
||||
|
||||
<!-- This dependency is needed and is need on TOP to use GWT UI BInder
|
||||
without old Xerces version of gCore complaining -->
|
||||
|
@ -65,7 +65,19 @@
|
|||
<version>2.9.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.common</groupId>
|
||||
<artifactId>authorization-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.gcube.common</groupId>
|
||||
<artifactId>common-authorization</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.gcube.common.portal</groupId>
|
||||
<artifactId>portal-manager</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.gwtbootstrap</groupId>
|
||||
<artifactId>gwt-bootstrap</artifactId>
|
||||
|
@ -89,6 +101,19 @@
|
|||
<artifactId>accesslogger</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- WebSocket dep (does not work on Jetty) -->
|
||||
<dependency>
|
||||
<groupId>org.realityforge.gwt.websockets</groupId>
|
||||
<artifactId>gwt-websockets</artifactId>
|
||||
<version>1.1.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.websocket</groupId>
|
||||
<artifactId>javax.websocket-api</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- FWS -->
|
||||
<dependency>
|
||||
<groupId>org.gcube.resources.discovery</groupId>
|
||||
|
@ -174,7 +199,7 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.liferay.portal</groupId>
|
||||
<artifactId>portal-service</artifactId>
|
||||
|
|
|
@ -442,7 +442,7 @@ public class AppController implements SubscriberInterface {
|
|||
public void onFileDownloadEvent(FileDownloadEvent fileDownloadEvent) {
|
||||
|
||||
if(fileDownloadEvent!=null && fileDownloadEvent.getItemIdentifier()!=null){
|
||||
AppControllerExplorer.getEventBus().fireEvent(new FileDownloadEvent(fileDownloadEvent.getItemIdentifier(), fileDownloadEvent.getItemName(), fileDownloadEvent.getDownloadType()));
|
||||
AppControllerExplorer.getEventBus().fireEvent(new FileDownloadEvent(fileDownloadEvent.getItemIdentifier(), fileDownloadEvent.getItemName(), fileDownloadEvent.getDownloadType(), fileDownloadEvent.isFolder()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -309,7 +309,8 @@ public class GxtGridFilterGroupPanel extends LayoutContainer {
|
|||
case DOCUMENT:
|
||||
case URL_DOCUMENT:
|
||||
case EXTERNAL_RESOURCE_LINK:
|
||||
AppController.getEventBus().fireEvent(new FileDownloadEvent(target.getIdentifier(), target.getName(), DownloadType.SHOW));
|
||||
|
||||
AppController.getEventBus().fireEvent(new FileDownloadEvent(target.getIdentifier(), target.getName(), DownloadType.SHOW, (target.isDirectory() || target.isVreFolder())));
|
||||
break;
|
||||
case EXTERNAL_URL:
|
||||
AppController.getEventBus().fireEvent(new OpenUrlEvent(target));
|
||||
|
|
|
@ -524,8 +524,7 @@ public class GxtToolBarItemFunctionality {
|
|||
public void componentSelected(ButtonEvent ce) {
|
||||
|
||||
final FileGridModel fileGridModel = gridGroupViewContainer.getSelectedItem();
|
||||
|
||||
AppController.getEventBus().fireEvent(new FileDownloadEvent(fileGridModel.getIdentifier(), fileGridModel.getName(), DownloadType.DOWNLOAD));
|
||||
AppController.getEventBus().fireEvent(new FileDownloadEvent(fileGridModel.getIdentifier(), fileGridModel.getName(), DownloadType.DOWNLOAD, (fileGridModel.isDirectory() || fileGridModel.isVreFolder())));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -554,7 +553,7 @@ public class GxtToolBarItemFunctionality {
|
|||
else if(fileGridModel.getGXTFolderItemType().equals(GXTFolderItemTypeEnum.REPORT) || fileGridModel.getGXTFolderItemType().equals(GXTFolderItemTypeEnum.REPORT_TEMPLATE))
|
||||
AppController.getEventBus().fireEvent(new OpenReportsEvent(fileGridModel));
|
||||
else
|
||||
AppController.getEventBus().fireEvent(new FileDownloadEvent(fileGridModel.getIdentifier(), fileGridModel.getName(), DownloadType.SHOW));
|
||||
AppController.getEventBus().fireEvent(new FileDownloadEvent(fileGridModel.getIdentifier(), fileGridModel.getName(), DownloadType.SHOW,(fileGridModel.isDirectory() || fileGridModel.isVreFolder())));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
package org.gcube.portlets.user.workspace.server;
|
||||
|
||||
import static org.gcube.common.authorization.client.Constants.authorizationService;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.websocket.OnClose;
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.OnOpen;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.gcube.common.authorization.library.provider.UserInfo;
|
||||
import org.gcube.common.homelibrary.home.HomeLibrary;
|
||||
import org.gcube.common.homelibrary.home.exceptions.InternalErrorException;
|
||||
import org.gcube.common.homelibrary.home.workspace.Workspace;
|
||||
import org.gcube.common.homelibrary.home.workspace.WorkspaceFolder;
|
||||
import org.gcube.common.homelibrary.home.workspace.WorkspaceItem;
|
||||
import org.gcube.common.homelibrary.home.workspace.exceptions.ItemNotFoundException;
|
||||
import org.gcube.common.homelibrary.util.zip.ZipUtil;
|
||||
import org.gcube.common.portal.PortalContext;
|
||||
import org.gcube.common.scope.api.ScopeProvider;
|
||||
import org.gcube.portlets.user.workspace.client.ConstantsExplorer;
|
||||
|
||||
@ServerEndpoint(value = "/downloadfolder", subprotocols = { "downloadfolder" })
|
||||
public class DownloadFolderWebSocketServer {
|
||||
|
||||
|
||||
protected static Logger _log = Logger.getLogger(DownloadFolderWebSocketServer.class);
|
||||
|
||||
private static Set<Session> peers = Collections.synchronizedSet( new HashSet<Session>() );
|
||||
|
||||
@OnOpen
|
||||
public void onOpen( final Session session ) {
|
||||
_log.debug( "onOpen(" + session.getId() + ")" );
|
||||
peers.add( session );
|
||||
}
|
||||
|
||||
@OnClose
|
||||
public void onClose( final Session session ) {
|
||||
_log.debug( "onClose(" + session.getId() + ")" );
|
||||
peers.remove( session );
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public void onMessage( final String message, final Session session ) {
|
||||
_log.info( "onMessage(" + message + "," + session.getId() + ")" );
|
||||
for ( final Session peer : peers )
|
||||
{
|
||||
if ( peer.getId().equals( session.getId() ) ) {
|
||||
if (message.startsWith(ConstantsExplorer.DOWNLOAD_WORKSPACE_FOLDER_PROTOCOL_DO_ZIP)) {
|
||||
String itemId = message.split(":")[1];
|
||||
if(itemId==null || itemId.isEmpty()){
|
||||
peer.getAsyncRemote().sendText(ConstantsExplorer.DOWNLOAD_WORKSPACE_FOLDER_PROTOCOL_ERROR_NOT_FOUND);
|
||||
} else {
|
||||
peer.getAsyncRemote().sendText(ConstantsExplorer.DOWNLOAD_WORKSPACE_FOLDER_PROTOCOL_ZIPPING);
|
||||
String username = message.split(":")[2];
|
||||
String absolutePath = zipFolder(itemId, peer, username);
|
||||
peer.getAsyncRemote().sendText(absolutePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
private final static String DEFAULT_ROLE = "OrganizationMember";
|
||||
private static void setAuthorizationToken(String username) throws Exception {
|
||||
|
||||
String scope = "/"+PortalContext.getConfiguration().getInfrastructureName();
|
||||
ScopeProvider.instance.set(scope);
|
||||
_log.debug("calling service token on scope " + scope);
|
||||
List<String> userRoles = new ArrayList<>();
|
||||
userRoles.add(DEFAULT_ROLE);
|
||||
String token = authorizationService().generateUserToken(new UserInfo(username, userRoles), scope);
|
||||
_log.debug("received token: "+token);
|
||||
_log.info("Security token set in session for: "+username + " on " + scope);
|
||||
}
|
||||
|
||||
private String zipFolder(String itemId, Session peer, String username) {
|
||||
|
||||
_log.info("FOLDER DOWNLOAD REQUEST itemId="+itemId + " user=" + username);
|
||||
Workspace wa = null;
|
||||
try {
|
||||
setAuthorizationToken(username);
|
||||
wa = HomeLibrary.getUserWorkspace(username);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (wa == null) {
|
||||
peer.getAsyncRemote().sendText(ConstantsExplorer.DOWNLOAD_WORKSPACE_FOLDER_PROTOCOL_ERROR_SESSION_EXPIRED);
|
||||
return null;
|
||||
}
|
||||
|
||||
WorkspaceItem item;
|
||||
try {
|
||||
|
||||
item = wa.getItem(itemId);
|
||||
try{
|
||||
//ACCOUNTING
|
||||
item.markAsRead(true);
|
||||
} catch (InternalErrorException e) {
|
||||
_log.error("Requested item "+itemId+" has thrown an internal error exception",e);
|
||||
}
|
||||
|
||||
} catch (ItemNotFoundException e) {
|
||||
_log.error("Requested item "+itemId+" not found",e);
|
||||
peer.getAsyncRemote().sendText(ConstantsExplorer.DOWNLOAD_WORKSPACE_FOLDER_PROTOCOL_ERROR_NOT_FOUND);
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (item.getType()) {
|
||||
case SHARED_FOLDER:
|
||||
case FOLDER:{
|
||||
try {
|
||||
File tmpZip = ZipUtil.zipFolder((WorkspaceFolder) item);
|
||||
|
||||
Path tmpDir = Files.createTempDirectory("workspace_temp");
|
||||
|
||||
File toCopy = new File(tmpDir.toAbsolutePath()+File.separator+item.getName());
|
||||
copyFileUsingFileChannels(tmpZip, toCopy);
|
||||
_log.info("Zipped folder in="+toCopy.getAbsolutePath());
|
||||
tmpZip.deleteOnExit();
|
||||
return toCopy.getAbsolutePath();
|
||||
} catch (Exception e) {
|
||||
_log.error("Error during folder compression "+itemId,e);
|
||||
peer.getAsyncRemote().sendText(ConstantsExplorer.DOWNLOAD_WORKSPACE_FOLDER_PROTOCOL_ERROR_DURING_COMPRESSION);
|
||||
}
|
||||
}
|
||||
default:
|
||||
_log.error("Error during folder compression "+itemId);
|
||||
peer.getAsyncRemote().sendText(ConstantsExplorer.DOWNLOAD_WORKSPACE_FOLDER_PROTOCOL_ERROR_NOT_A_FOLDER);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@SuppressWarnings("resource")
|
||||
private static void copyFileUsingFileChannels(File source, File dest) throws IOException {
|
||||
FileChannel inputChannel = null;
|
||||
FileChannel outputChannel = null;
|
||||
try {
|
||||
inputChannel = new FileInputStream(source).getChannel();
|
||||
outputChannel = new FileOutputStream(dest).getChannel();
|
||||
outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
|
||||
} finally {
|
||||
inputChannel.close();
|
||||
outputChannel.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
|
||||
<!-- To Comment out -->
|
||||
<!-- <set-property name="user.agent" value="gecko1_8,safari" /> -->
|
||||
<!-- <set-property name="user.agent" value="safari" /> -->
|
||||
|
||||
<!-- <inherits name='org.gcube.portlets.widgets.guidedtour.GuidedTour' /> -->
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
|||
<!-- Inherits widget -->
|
||||
<inherits
|
||||
name='org.gcube.portlets.widgets.ckandatapublisherwidget.CKanMetadataPublisher' />
|
||||
|
||||
<inherits name="org.realityforge.gwt.websockets.WebSockets" />
|
||||
<!-- Specify the app entry point class. -->
|
||||
<entry-point
|
||||
class='org.gcube.portlets.user.workspace.client.WorkspacePortlet' />
|
||||
|
|
|
@ -30,6 +30,11 @@
|
|||
<servlet-class>org.gcube.portlets.user.workspace.server.DownloadServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>DownloadFolderServlet</servlet-name>
|
||||
<servlet-class>org.gcube.portlets.user.workspace.server.DownloadFolderServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<!-- Servlets -->
|
||||
<servlet>
|
||||
<servlet-name>WorkspaceService</servlet-name>
|
||||
|
@ -148,6 +153,12 @@
|
|||
<url-pattern>/workspace/DownloadService</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>DownloadFolderServlet</servlet-name>
|
||||
<url-pattern>/workspace/DownloadFolderServlet</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
|
||||
<!-- <servlet-mapping> -->
|
||||
<!-- <servlet-name>UploadService</servlet-name> -->
|
||||
<!-- <url-pattern>/workspace/UploadService</url-pattern> -->
|
||||
|
|
Loading…
Reference in New Issue