466 lines
20 KiB
Java
466 lines
20 KiB
Java
|
|
/*
|
||
|
|
* Copyright (c) 2005,2009 Declarative Engineering LLC.
|
||
|
|
* All rights reserved. This program and the accompanying materials
|
||
|
|
* are made available under the terms of the Declarative Engineering LLC
|
||
|
|
* verson 1 which accompanies this distribution, and is available at
|
||
|
|
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||
|
|
*/
|
||
|
|
package com.foundation.tcv.server.controller;
|
||
|
|
|
||
|
|
import com.common.util.*;
|
||
|
|
import com.common.debug.*;
|
||
|
|
import com.common.orb.Orb;
|
||
|
|
import com.common.thread.*;
|
||
|
|
import com.common.util.optimized.*;
|
||
|
|
import com.foundation.controller.*;
|
||
|
|
import com.foundation.tcv.server.util.*;
|
||
|
|
import com.foundation.tcv.view.*;
|
||
|
|
import com.foundation.tcv.controller.*;
|
||
|
|
import com.foundation.view.IRemoteSessionContext;
|
||
|
|
|
||
|
|
/*
|
||
|
|
* Manages the session for a perticular view. Each view in the session will create one instance of the session view controller.
|
||
|
|
*/
|
||
|
|
public class SessionViewController implements com.foundation.view.IRemoteViewContext, ISessionViewController {
|
||
|
|
/** The mapping of server side components indexed by their component number. */
|
||
|
|
private IntObjectHashMap componentMap = new IntObjectHashMap(20);
|
||
|
|
/** The next available component number to be used for relating components on the client with components on the server. */
|
||
|
|
private int nextComponentNumber = 1;
|
||
|
|
/** A queue of messages waiting to be sent to the client. */
|
||
|
|
private LiteList outgoingMessageQueue = new LiteList(100);
|
||
|
|
/** The number of holds placed on outgoing messages. */
|
||
|
|
private int messageHoldCount = 0;
|
||
|
|
/** Will be non-null as long as the view is not yet released. */
|
||
|
|
private SessionController sessionController = null;
|
||
|
|
/** The number the view is known by. */
|
||
|
|
private long sessionViewNumber = 0L;
|
||
|
|
/** Will be non-null as long as the view is not yet released. */
|
||
|
|
private RemoteViewController viewController = null;
|
||
|
|
/** Whether the session view controller has started or finished the process of shutting down. */
|
||
|
|
private volatile boolean isShutdown = false;
|
||
|
|
/** Tracks the number of incomplete two-way messages being processed. If this value is greater than zero then the event loop thread will only process messages initiated by its self, or via the Orb. Values greater than 1 indicate that nested 2-way calls are occuring. */
|
||
|
|
private int twoWayMessageCounter = 0;
|
||
|
|
/** A task to send the queued messages. This is only used if the messages are not high priority and if there may be more messages in the very near future. */
|
||
|
|
private Runnable sendMessageTask = null;
|
||
|
|
/**
|
||
|
|
* SessionViewController constructor.
|
||
|
|
*/
|
||
|
|
public SessionViewController(SessionController sessionController, long sessionViewNumber, RemoteViewController viewController) {
|
||
|
|
super();
|
||
|
|
|
||
|
|
this.sessionController = sessionController;
|
||
|
|
this.sessionViewNumber = sessionViewNumber;
|
||
|
|
this.viewController = viewController;
|
||
|
|
}//SessionViewController()//
|
||
|
|
/**
|
||
|
|
* Gets the session view number.
|
||
|
|
* @return The number identifying the view.
|
||
|
|
*/
|
||
|
|
public long getNumber() {
|
||
|
|
return sessionViewNumber;
|
||
|
|
}//getNumber()//
|
||
|
|
/**
|
||
|
|
* Gets the session controller for this view.
|
||
|
|
* @return The view's session which defines which client the view is displayed on.
|
||
|
|
*/
|
||
|
|
public SessionController getSessionController() {
|
||
|
|
return sessionController;
|
||
|
|
}//getSessionController()//
|
||
|
|
/**
|
||
|
|
* Gets the read only request handler reference used by the view to manage threading and message processing.
|
||
|
|
* @return The handler that manages messaging within the view.
|
||
|
|
*/
|
||
|
|
public EventLoop getViewRequestHandler() {
|
||
|
|
return getSessionController().getViewRequestHandler();
|
||
|
|
}//getViewRequestHandler()//
|
||
|
|
/**
|
||
|
|
* Registers a component in the view.
|
||
|
|
* @param component The component to be registered.
|
||
|
|
* @return The component's assigned number which can be used to communicate with the client side component.
|
||
|
|
*/
|
||
|
|
public synchronized int registerComponent(Object component) {
|
||
|
|
int number = nextComponentNumber++;
|
||
|
|
|
||
|
|
componentMap.put(number, component);
|
||
|
|
|
||
|
|
return number;
|
||
|
|
}//registerComponent()//
|
||
|
|
/**
|
||
|
|
* Gets the view component with the given number.
|
||
|
|
* @param componentNumber The view unique number for the desired component.
|
||
|
|
* @return The component with the assigned number.
|
||
|
|
*/
|
||
|
|
public synchronized Object getComponent(int componentNumber) {
|
||
|
|
return componentMap.get(componentNumber);
|
||
|
|
}//getComponent()//
|
||
|
|
/**
|
||
|
|
* Closes the view on the server and releases it.
|
||
|
|
* <p><b>Only the view controller should call this method.</b></p>
|
||
|
|
* @see #closeView()
|
||
|
|
*/
|
||
|
|
public void close() {
|
||
|
|
boolean releaseView = false;
|
||
|
|
|
||
|
|
synchronized(this) {
|
||
|
|
if(!isShutdown) {
|
||
|
|
if(sessionController != null) {
|
||
|
|
//TODO: Removing this code since it ignores queued messages waiting to be sent to the client. This could cause problems when closing the view from the server though.
|
||
|
|
//Notify the client that the view is closed.//
|
||
|
|
//sessionController.sendMessages(sessionViewNumber, new LiteList(new com.foundation.tcv.view.ViewMessage(0, IAbstractViewComponent.MESSAGE_CLOSE_VIEW, null, true)), false, true);
|
||
|
|
sendMessage(new com.foundation.tcv.view.ViewMessage(0, IAbstractRemoteViewComponent.MESSAGE_CLOSE_VIEW, null, null, 0, 0, true), false);
|
||
|
|
}//if//
|
||
|
|
|
||
|
|
this.viewController = null;
|
||
|
|
this.componentMap.removeAll();
|
||
|
|
this.isShutdown = true;
|
||
|
|
releaseView = true;
|
||
|
|
}//if//
|
||
|
|
}//synchronized//
|
||
|
|
|
||
|
|
if(releaseView) {
|
||
|
|
//Release the view.//
|
||
|
|
sessionController.releaseView(sessionViewNumber);
|
||
|
|
}//if//
|
||
|
|
}//close()//
|
||
|
|
/**
|
||
|
|
* Closes the view by notifying the primary view controller that it should close.
|
||
|
|
* TODO: Can we merge the two close methods?
|
||
|
|
*/
|
||
|
|
protected void forcedClose() {
|
||
|
|
boolean releaseView = false;
|
||
|
|
RemoteViewController viewController = null;
|
||
|
|
|
||
|
|
synchronized(this) {
|
||
|
|
if(!isShutdown) {
|
||
|
|
viewController = this.viewController;
|
||
|
|
this.viewController = null;
|
||
|
|
this.componentMap.removeAll();
|
||
|
|
this.isShutdown = true;
|
||
|
|
releaseView = true;
|
||
|
|
}//if//
|
||
|
|
}//synchronized//
|
||
|
|
|
||
|
|
if(releaseView) {
|
||
|
|
if(viewController != null) {
|
||
|
|
viewController.close();
|
||
|
|
}//if//
|
||
|
|
|
||
|
|
//Release the view.//
|
||
|
|
sessionController.releaseView(sessionViewNumber);
|
||
|
|
}//if//
|
||
|
|
}//forcedClose()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.view.IRemoteViewContext#isValid()
|
||
|
|
*/
|
||
|
|
public synchronized boolean isValid() {
|
||
|
|
return sessionController != null;
|
||
|
|
}//isValid()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.view.IRemoteViewContext#getSessionContext()
|
||
|
|
*/
|
||
|
|
public IRemoteSessionContext getSessionContext() {
|
||
|
|
return sessionController;
|
||
|
|
}//getSessionContext()//
|
||
|
|
/**
|
||
|
|
* Increments the hold count on the message queue so that messages will be queued up until the count reaches zero.
|
||
|
|
*/
|
||
|
|
public synchronized void incrementMessageHoldCount() {
|
||
|
|
messageHoldCount++;
|
||
|
|
// Debug.log("(" + sessionViewNumber + ") Incremented Hold Count | now: " + messageHoldCount);
|
||
|
|
}//incrementMessageHoldCount()//
|
||
|
|
/**
|
||
|
|
* Decrements the hold count on the message queue so that messages will be queued up until the count reaches zero.
|
||
|
|
*/
|
||
|
|
public synchronized void decrementMessageHoldCount() {
|
||
|
|
messageHoldCount--;
|
||
|
|
// Debug.log("(" + sessionViewNumber + ") Decrmented Hold Count | now: " + messageHoldCount);
|
||
|
|
|
||
|
|
if((messageHoldCount == 0) && (outgoingMessageQueue.getSize() > 0)) {
|
||
|
|
sendMessage(null, false, true);
|
||
|
|
}//if//
|
||
|
|
}//decrementMessageHoldCount()//
|
||
|
|
/**
|
||
|
|
* Sends a message to the client.
|
||
|
|
* @param viewMessage The message to be sent.
|
||
|
|
* @param isSynchronous Whether the message is synchronous (requiring a response). Synchronous messages are sent without delay and are unaffected by holds.
|
||
|
|
* @return Sends a message to the client and returns the response to the message if the message is fully synchronous.
|
||
|
|
*/
|
||
|
|
public Object sendMessage(ViewMessage viewMessage, boolean isSynchronous) {
|
||
|
|
return sendMessage(viewMessage, isSynchronous, isSynchronous);
|
||
|
|
}//sendMessage()//
|
||
|
|
/**
|
||
|
|
* Sends a message to the client.
|
||
|
|
* @param viewMessage The message to be sent.
|
||
|
|
* @param isSynchronous Whether the message is synchronous (requiring a response). Synchronous messages are sent without delay and are unaffected by holds.
|
||
|
|
* @param sendImmediately Whether the messages should be sent inlined versus waiting a very short time for additional messages.
|
||
|
|
* @return Sends a message to the client and returns the response to the message if the message is fully synchronous.
|
||
|
|
*/
|
||
|
|
public Object sendMessage(ViewMessage viewMessage, boolean isSynchronous, boolean sendImmediately) {
|
||
|
|
Object result = null;
|
||
|
|
IList messages = null;
|
||
|
|
|
||
|
|
synchronized(this) {
|
||
|
|
//The view message may be null if the component could not create one due to the view being in the process of shutting down. Gracefully ignore the null message.//
|
||
|
|
if(viewMessage != null) {
|
||
|
|
//If the message being sent is the view close message then clear any unnecessary pending messages since they are irrelevant.//
|
||
|
|
if(viewMessage.getControlNumber() == 0 && viewMessage.getMessageNumber() == IAbstractRemoteViewComponent.MESSAGE_CLOSE_VIEW) {
|
||
|
|
for(int index = outgoingMessageQueue.getSize() - 1; index >= 0; index--) {
|
||
|
|
ViewMessage next = (ViewMessage) outgoingMessageQueue.get(index);
|
||
|
|
|
||
|
|
//Keep messages sent to either the view controller on the client, or to the view's primary component since most of these messages are likely necessary (eg: release, and set visible messages).//
|
||
|
|
if(!(next.getControlNumber() == 0 || next.getControlNumber() == 1)) {
|
||
|
|
outgoingMessageQueue.remove(index);
|
||
|
|
}//if//
|
||
|
|
}//while//
|
||
|
|
}//if//
|
||
|
|
|
||
|
|
outgoingMessageQueue.add(viewMessage);
|
||
|
|
}//if//
|
||
|
|
|
||
|
|
//Create a list of messages to be sent if this is a synchronous message.//
|
||
|
|
if((isSynchronous) && (outgoingMessageQueue.getSize() > 0)) {
|
||
|
|
//Create a list of the queued messages.//
|
||
|
|
messages = new LiteList((ICollection) outgoingMessageQueue);
|
||
|
|
outgoingMessageQueue.removeAll();
|
||
|
|
}//if//
|
||
|
|
else if((twoWayMessageCounter == 0) && (sendMessageTask == null)) {
|
||
|
|
//If a message hold is in place then don't send now.//
|
||
|
|
if(messageHoldCount == 0) {
|
||
|
|
if(!sendImmediately) {
|
||
|
|
//Create a task to send queued messages to the client in a quarter second.//
|
||
|
|
sendMessageTask = new Runnable() {
|
||
|
|
public void run() {
|
||
|
|
LiteList messages = null;
|
||
|
|
|
||
|
|
//Make sure that this task is still valid and is not being superceeded.//
|
||
|
|
synchronized(SessionViewController.this) {
|
||
|
|
if(sendMessageTask == this) {
|
||
|
|
//Cleanup after the task.//
|
||
|
|
sendMessageTask = null;
|
||
|
|
//Create a list of the queued messages.//
|
||
|
|
messages = new LiteList((ICollection) outgoingMessageQueue);
|
||
|
|
outgoingMessageQueue.removeAll();
|
||
|
|
}//if//
|
||
|
|
}//synchronized//
|
||
|
|
|
||
|
|
if(messages != null) {
|
||
|
|
//Send the server the queued messages.//
|
||
|
|
sendMessages(messages, false);
|
||
|
|
}//if//
|
||
|
|
|
||
|
|
ActiveScheduler.getSingleton().remove(this);
|
||
|
|
}//run()//
|
||
|
|
};
|
||
|
|
ActiveScheduler.getSingleton().add(sendMessageTask, 50);
|
||
|
|
}//if//
|
||
|
|
else {
|
||
|
|
//Create a list of the queued messages.//
|
||
|
|
messages = new LiteList((ICollection) outgoingMessageQueue);
|
||
|
|
outgoingMessageQueue.removeAll();
|
||
|
|
}//else//
|
||
|
|
}//if//
|
||
|
|
}//else if//
|
||
|
|
}//synchronized()//
|
||
|
|
|
||
|
|
//Send the message now if we are not queuing messages or the message is not asynchronous.//
|
||
|
|
if(messages != null) {
|
||
|
|
result = sendMessages(messages, isSynchronous);
|
||
|
|
}//if//
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}//sendMessage()//
|
||
|
|
/**
|
||
|
|
* Sends queued messages to the client.
|
||
|
|
* @param messages The messages to be sent to the client.
|
||
|
|
* @param isSynchronous Whether the call requires waiting for a result.
|
||
|
|
* @return Sends a message to the client and returns the response to the message if the message is fully synchronous.
|
||
|
|
*/
|
||
|
|
private Object sendMessages(IList messages, boolean isSynchronous) {
|
||
|
|
return sendMessages(messages, isSynchronous, twoWayMessageCounter > 0);
|
||
|
|
}//sendMessage()//
|
||
|
|
/**
|
||
|
|
* Sends queued messages to the client.
|
||
|
|
* @param messages The messages to be sent to the client.
|
||
|
|
* @param isSynchronous Whether the call requires waiting for a result.
|
||
|
|
* @param twoWayMessageContext Whether the messages are being sent under a two way message context, meaning the remote system sent a two way message and these are a result of the two way message.
|
||
|
|
* @return Sends a message to the client and returns the response to the message if the message is fully synchronous.
|
||
|
|
*/
|
||
|
|
private Object sendMessages(IList messages, boolean isSynchronous, boolean twoWayMessageContext) {
|
||
|
|
Object result = null;
|
||
|
|
SessionController sessionController = getSessionController();
|
||
|
|
|
||
|
|
if((messages.getSize() > 0) && (sessionController != null)) {
|
||
|
|
if(DEBUG) {
|
||
|
|
Debug.log("Sending Messages: (thread: " + Thread.currentThread() + ")");
|
||
|
|
|
||
|
|
for(int index = 0; index < messages.getSize(); index++) {
|
||
|
|
ViewMessage next = (ViewMessage) messages.get(index);
|
||
|
|
Debug.log(" Msg #: " + next.getMessageNumber() + " Data: '" + next.getMessageData() + "'");
|
||
|
|
}//for//
|
||
|
|
}//if//
|
||
|
|
|
||
|
|
//Send the queued messages to the client and return immediatly.//
|
||
|
|
result = sessionController.sendMessages(sessionViewNumber, messages, isSynchronous, twoWayMessageContext);
|
||
|
|
}//if//
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}//sendMessage()//
|
||
|
|
/**
|
||
|
|
* Called by the session controller when it starts processing on a two way client initiated message.
|
||
|
|
*/
|
||
|
|
public synchronized void processingTwoWayStarted() {
|
||
|
|
twoWayMessageCounter++;
|
||
|
|
}//processingTwoWayStarted()//
|
||
|
|
/**
|
||
|
|
* Called by the session controller when it finishes processing on a two way client initiated message.
|
||
|
|
*/
|
||
|
|
public void processingTwoWayFinished() {
|
||
|
|
LiteList messages = null;
|
||
|
|
|
||
|
|
synchronized(this) {
|
||
|
|
twoWayMessageCounter--;
|
||
|
|
|
||
|
|
//Notify all waiting threads.//
|
||
|
|
if(twoWayMessageCounter == 0) {
|
||
|
|
if(outgoingMessageQueue.getSize() > 0) {
|
||
|
|
//Create a list of the queued messages.//
|
||
|
|
messages = new LiteList((ICollection) outgoingMessageQueue);
|
||
|
|
outgoingMessageQueue.removeAll();
|
||
|
|
}//if//
|
||
|
|
|
||
|
|
notifyAll();
|
||
|
|
}//if//
|
||
|
|
}//synchronized//
|
||
|
|
|
||
|
|
if(messages != null) {
|
||
|
|
//Send the server the queued messages.//
|
||
|
|
sendMessages(messages, false, true);
|
||
|
|
}//if//
|
||
|
|
}//processingTwoWayFinished()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.view.IRemoteViewContext#execute(com.common.thread.IRunnable)
|
||
|
|
*/
|
||
|
|
public Object execute(IRunnable runnable) {
|
||
|
|
EventLoop eventLoop = getSessionController().getEventLoop();
|
||
|
|
|
||
|
|
//Note: This method is synchronized such that new 2-way messages will get added to the event queue after this request.//
|
||
|
|
//Block messages comming from the application as long as the thread is not the event thread and the server is processing a client initiated 2-way message associated with this view.//
|
||
|
|
if(!eventLoop.isRequestThread()) {
|
||
|
|
synchronized(this) { //TODO: Ideally this would be around the whole method, but the execute call at the bottom blocks which causes deadlocks. Find a way to ensure the event thread gets the runnable before a two-way message from the client.//
|
||
|
|
while(twoWayMessageCounter != 0) {
|
||
|
|
try {
|
||
|
|
wait(0);
|
||
|
|
}//try//
|
||
|
|
catch(InterruptedException e) {
|
||
|
|
Debug.handle(e);
|
||
|
|
}//catch//
|
||
|
|
}//while//
|
||
|
|
}//synchronized//
|
||
|
|
}//if//
|
||
|
|
|
||
|
|
return eventLoop.execute(runnable, true);
|
||
|
|
}//execute()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.view.IRemoteViewContext#executeAsync(com.common.thread.IRunnable)
|
||
|
|
*/
|
||
|
|
public synchronized void executeAsync(final IRunnable runnable) {
|
||
|
|
final EventLoop eventLoop = getSessionController().getEventLoop();
|
||
|
|
|
||
|
|
//Note: This method is synchronized such that new 2-way messages will get added to the event queue after this request.//
|
||
|
|
//Avoid threading if the message can be immediatly added to the event queue.//
|
||
|
|
if((!eventLoop.isRequestThread()) && (twoWayMessageCounter != 0)) {
|
||
|
|
//Thread the adding of the asynch runnable so that the caller doesn't have to wait.//
|
||
|
|
ThreadService.run(new Runnable() {
|
||
|
|
public void run() {
|
||
|
|
synchronized(SessionViewController.this) {
|
||
|
|
//Block messages comming from the application as long as the thread is not the event thread and the server is processing a client initiated 2-way message associated with this view.//
|
||
|
|
while(twoWayMessageCounter != 0) {
|
||
|
|
try {
|
||
|
|
SessionViewController.this.wait(3000);
|
||
|
|
}//try//
|
||
|
|
catch(InterruptedException e) {
|
||
|
|
Debug.handle(e);
|
||
|
|
}//catch//
|
||
|
|
}//while//
|
||
|
|
|
||
|
|
eventLoop.execute(runnable, false);
|
||
|
|
}//synchronized//
|
||
|
|
}//run()//
|
||
|
|
});
|
||
|
|
}//if//
|
||
|
|
else {
|
||
|
|
eventLoop.execute(runnable, false);
|
||
|
|
}//else//
|
||
|
|
}//executeAsync()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.view.IRemoteViewContext#remoteOpen(java.lang.String, java.lang.String, byte[])
|
||
|
|
*/
|
||
|
|
public void remoteOpen(String prefix, String extension, byte[] data) {
|
||
|
|
sendMessage(new ViewMessage(0, MESSAGE_OPEN_TEMP_FILE, new Object[] {extension, prefix, data}, null, 0, 0, false), false);
|
||
|
|
}//remoteOpen()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.view.IRemoteViewContext#remoteLoad(java.lang.String[])
|
||
|
|
*/
|
||
|
|
public LoadData[] remoteLoad(String[] extensions, boolean allowMultiple) {
|
||
|
|
Object[][] data = (Object[][]) sendMessage(new ViewMessage(0, MESSAGE_LOAD_FROM_FILE, new Object[] {extensions, allowMultiple ? Boolean.TRUE : Boolean.FALSE}, null, 0, 0, false), true);
|
||
|
|
LoadData[] result = null;
|
||
|
|
|
||
|
|
if(data != null) {
|
||
|
|
result = new LoadData[data.length];
|
||
|
|
|
||
|
|
for(int index = 0; index < result.length; index++) {
|
||
|
|
result[index] = new LoadData((String) data[index][0], (byte[]) data[index][1]);
|
||
|
|
}//for//
|
||
|
|
}//if//
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}//remoteLoad()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.view.IRemoteViewContext#remoteSave(java.lang.String, byte[])
|
||
|
|
*/
|
||
|
|
public void remoteSave(String defaultName, byte[] data) {
|
||
|
|
sendMessage(new ViewMessage(0, MESSAGE_SAVE_TO_FILE, new Object[] {defaultName, data}, null, 0, 0, false), false);
|
||
|
|
}//remoteSave()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.view.IRemoteViewContext#remoteStreamedSaveToFile(java.lang.String, java.lang.String, long, com.common.util.IContentStream)
|
||
|
|
*/
|
||
|
|
public String remoteStreamedSaveToFile(String defaultPath, String defaultName, long contentSize, IContentStream contentStream) {
|
||
|
|
return (String) sendMessage(new ViewMessage(0, MESSAGE_SAVE_TO_FILE_STREAMED, new Object[] {defaultPath, defaultName, new Long(contentSize)}, Orb.getProxy(contentStream, IContentStream.class), 0, 0, false), true);
|
||
|
|
}//remoteStreamedSaveToFile()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.view.IRemoteViewContext#remoteStreamedLoadFromFile(java.lang.String[], boolean)
|
||
|
|
*/
|
||
|
|
public LoadStreamedData[] remoteStreamedLoadFromFile(String[] extensions, boolean allowMultiple) {
|
||
|
|
return remoteStreamedLoadFromFile(extensions, allowMultiple, null, null);
|
||
|
|
}//remoteStreamedLoadFromFile()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.view.IRemoteViewContext#remoteStreamedLoadFromFile(java.lang.String[], boolean, java.lang.String, java.lang.String)
|
||
|
|
*/
|
||
|
|
public LoadStreamedData[] remoteStreamedLoadFromFile(String[] extensions, boolean allowMultiple, String fileName, String filterPath) {
|
||
|
|
return (LoadStreamedData[]) sendMessage(new ViewMessage(0, MESSAGE_LOAD_FROM_FILE_STREAMED, extensions, fileName == null && filterPath == null ? null : new Object[] {fileName, filterPath}, allowMultiple ? 1 : 0, 0, false), true);
|
||
|
|
}//remoteStreamedLoadFromFile()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.view.IRemoteViewContext#remoteCollectFilesToRename(java.lang.String[], boolean, java.lang.String, java.lang.String)
|
||
|
|
*/
|
||
|
|
public String[] remoteCollectFilesToRename(String[] extensions, boolean allowMultiple, String fileName, String filterPath) {
|
||
|
|
return (String[]) sendMessage(new ViewMessage(0, MESSAGE_COLLECT_FILES_TO_RENAME, extensions, fileName == null && filterPath == null ? null : new Object[] {fileName, filterPath}, allowMultiple ? 1 : 0, 0, false), true);
|
||
|
|
}//remoteCollectFilesToRename()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.view.IRemoteViewContext#remoteRenameFiles(java.lang.String[], boolean)
|
||
|
|
*/
|
||
|
|
public void remoteRenameFiles(String[] newFileNames, boolean includesPaths) {
|
||
|
|
sendMessage(new ViewMessage(0, MESSAGE_RENAME_FILES, newFileNames, null, includesPaths ? 1 : 0, 0, false), true);
|
||
|
|
}//remoteRenameFiles()//
|
||
|
|
/* (non-Javadoc)
|
||
|
|
* @see com.foundation.view.IRemoteViewContext#remoteSaveToFilesStreamed(java.lang.String, java.lang.String[], com.common.util.IContentStream[])
|
||
|
|
*/
|
||
|
|
public int remoteSaveToFilesStreamed(String defaultPath, String[] fileNames, IContentStream[] contentStreams) {
|
||
|
|
IContentStream[] streamProxies = new IContentStream[contentStreams.length];
|
||
|
|
|
||
|
|
for(int index = 0; index < contentStreams.length; index++) {
|
||
|
|
streamProxies[index] = (IContentStream) Orb.getProxy(contentStreams[index], IContentStream.class);
|
||
|
|
}//for//
|
||
|
|
|
||
|
|
return ((Integer) sendMessage(new ViewMessage(0, MESSAGE_SAVE_TO_FILES_STREAMED, new Object[] {defaultPath, fileNames}, streamProxies, 0, 0, false), true)).intValue();
|
||
|
|
}//remoteSaveToFilesStreamed()//
|
||
|
|
}//SessionViewController//
|