mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Remote API exposure for benchmark client.
Benchmark client Note: - Loading types still need to be fleshed out - The content over RMI is weak, but sufficient for this use-case. - An all-round solution for RMI content serialization is needed for ContentReader and ContentWriter, probably using the RemotableInputStream, etc git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6783 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -14,3 +14,7 @@ avm.remote.host=localhost
|
|||||||
# AVMRemote API
|
# AVMRemote API
|
||||||
avm.remote.port=50500
|
avm.remote.port=50500
|
||||||
|
|
||||||
|
# Remote RMI services
|
||||||
|
rmi.services.remote.port=${avm.remote.port}
|
||||||
|
rmi.services.remote.host=${avm.remote.host}
|
||||||
|
|
||||||
|
71
config/alfresco/extension/remote-loader-context.xml
Normal file
71
config/alfresco/extension/remote-loader-context.xml
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN//EN"
|
||||||
|
"http://www.springframework.org/dtd/spring-beans.dtd">
|
||||||
|
|
||||||
|
<beans>
|
||||||
|
|
||||||
|
<!-- Remote FileFolderService exposure -->
|
||||||
|
|
||||||
|
<bean id="fileFolderRemoteServer" class="org.alfresco.repo.remote.FileFolderRemoteServer">
|
||||||
|
<property name="transactionService">
|
||||||
|
<ref bean="TransactionService"/>
|
||||||
|
</property>
|
||||||
|
<property name="fileFolderService">
|
||||||
|
<ref bean="FileFolderService"/>
|
||||||
|
</property>
|
||||||
|
<property name="authenticationService">
|
||||||
|
<ref bean="AuthenticationService"/>
|
||||||
|
</property>
|
||||||
|
<property name="mimetypeService">
|
||||||
|
<ref bean="MimetypeService"/>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="fileFolderRemoteRMI" class="org.springframework.remoting.rmi.RmiServiceExporter">
|
||||||
|
<property name="service">
|
||||||
|
<ref bean="fileFolderRemoteServer"/>
|
||||||
|
</property>
|
||||||
|
<property name="serviceInterface">
|
||||||
|
<value>org.alfresco.service.cmr.remote.FileFolderRemote</value>
|
||||||
|
</property>
|
||||||
|
<property name="serviceName">
|
||||||
|
<value>org.alfresco.FileFolderRemote</value>
|
||||||
|
</property>
|
||||||
|
<property name="registryPort">
|
||||||
|
<value>${rmi.services.remote.port}</value>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- Remote Loader exposure -->
|
||||||
|
|
||||||
|
<bean id="loaderRemoteServer" class="org.alfresco.repo.remote.LoaderRemoteServer">
|
||||||
|
<property name="transactionService">
|
||||||
|
<ref bean="TransactionService"/>
|
||||||
|
</property>
|
||||||
|
<property name="authenticationService">
|
||||||
|
<ref bean="AuthenticationService"/>
|
||||||
|
</property>
|
||||||
|
<property name="nodeService">
|
||||||
|
<ref bean="NodeService"/>
|
||||||
|
</property>
|
||||||
|
<property name="nodeDaoService">
|
||||||
|
<ref bean="nodeDaoService"/>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="loaderRemoteServerRMI" class="org.springframework.remoting.rmi.RmiServiceExporter">
|
||||||
|
<property name="service">
|
||||||
|
<ref bean="loaderRemoteServer"/>
|
||||||
|
</property>
|
||||||
|
<property name="serviceInterface">
|
||||||
|
<value>org.alfresco.service.cmr.remote.LoaderRemote</value>
|
||||||
|
</property>
|
||||||
|
<property name="serviceName">
|
||||||
|
<value>org.alfresco.LoaderRemote</value>
|
||||||
|
</property>
|
||||||
|
<property name="registryPort">
|
||||||
|
<value>${rmi.services.remote.port}</value>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
</beans>
|
@@ -492,4 +492,21 @@
|
|||||||
store.key.identifier = :storeIdentifier)
|
store.key.identifier = :storeIdentifier)
|
||||||
</query>
|
</query>
|
||||||
|
|
||||||
|
<query name="node.GetNodeCount">
|
||||||
|
select
|
||||||
|
count(node.id)
|
||||||
|
from
|
||||||
|
org.alfresco.repo.domain.hibernate.NodeImpl as node
|
||||||
|
</query>
|
||||||
|
|
||||||
|
<query name="node.GetNodeCountForStore">
|
||||||
|
select
|
||||||
|
count(node.id)
|
||||||
|
from
|
||||||
|
org.alfresco.repo.domain.hibernate.NodeImpl as node
|
||||||
|
where
|
||||||
|
node.store.key.protocol = :protocol and
|
||||||
|
node.store.key.identifier = :identifier
|
||||||
|
</query>
|
||||||
|
|
||||||
</hibernate-mapping>
|
</hibernate-mapping>
|
||||||
|
@@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.model.filefolder.loader;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A description of what the remote loader should do.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public abstract class AbstractLoaderThread extends Thread
|
||||||
|
{
|
||||||
|
protected final LoaderSession session;
|
||||||
|
protected final String loaderName;
|
||||||
|
protected final int testPeriod;
|
||||||
|
protected final int testTotal;
|
||||||
|
protected final int testLoadDepth;
|
||||||
|
|
||||||
|
private AtomicBoolean mustStop;
|
||||||
|
|
||||||
|
public AbstractLoaderThread(
|
||||||
|
LoaderSession session,
|
||||||
|
String loaderName,
|
||||||
|
int testPeriod,
|
||||||
|
int testTotal,
|
||||||
|
int testLoadDepth)
|
||||||
|
{
|
||||||
|
super(LoaderSession.THREAD_GROUP, "LoaderThread-" + loaderName);
|
||||||
|
|
||||||
|
this.session = session;
|
||||||
|
this.loaderName = loaderName;
|
||||||
|
this.testPeriod = testPeriod;
|
||||||
|
this.testTotal = testTotal;
|
||||||
|
this.testLoadDepth = testLoadDepth;
|
||||||
|
|
||||||
|
this.mustStop = new AtomicBoolean(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the running thread to exit at the first available opportunity.
|
||||||
|
*/
|
||||||
|
public void setStop()
|
||||||
|
{
|
||||||
|
mustStop.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String getSummary();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
int testCount = 0;
|
||||||
|
while (!mustStop.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Choose a server
|
||||||
|
int serverCount = session.getRemoteServers().size();
|
||||||
|
int serverIndex = random.nextInt(serverCount);
|
||||||
|
LoaderServerProxy serverProxy = session.getRemoteServers().get(serverIndex);
|
||||||
|
|
||||||
|
// Choose a working root node
|
||||||
|
int nodeCount = session.getWorkingRootNodeRefs().size();
|
||||||
|
int nodeIndex = random.nextInt(nodeCount);
|
||||||
|
NodeRef workingRootNodeRef = session.getWorkingRootNodeRefs().get(nodeIndex);
|
||||||
|
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
doLoading(serverProxy, workingRootNodeRef);
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
// Have we done this enough?
|
||||||
|
testCount++;
|
||||||
|
if (testCount > testTotal)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we wait or continue immediately
|
||||||
|
long duration = endTime - startTime;
|
||||||
|
long mustWait = (testPeriod * 1000L) - duration;
|
||||||
|
if (mustWait >= 5)
|
||||||
|
{
|
||||||
|
synchronized(this)
|
||||||
|
{
|
||||||
|
this.wait(mustWait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
session.logError(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param serverProxy the server to load
|
||||||
|
* @param workingRootNodeRef the root of the hierarchy to use
|
||||||
|
* @throws Exception any exception will be handled
|
||||||
|
*/
|
||||||
|
protected abstract void doLoading(
|
||||||
|
LoaderServerProxy serverProxy,
|
||||||
|
NodeRef workingRootNodeRef) throws Exception;
|
||||||
|
}
|
@@ -0,0 +1,365 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.model.filefolder.loader;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class that communicates with the remote FileFolder interface to perform
|
||||||
|
* loading of the system using the standard models.
|
||||||
|
* <p>
|
||||||
|
* TODO: The transport interface must be hidden behind and implementation
|
||||||
|
* of the standard FileFolderService interface.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public class FileFolderRemoteLoader
|
||||||
|
{
|
||||||
|
private static final String STORE_PROTOCOL = "FileFolderRemoteLoader";
|
||||||
|
|
||||||
|
private Properties properties;
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
private LoaderSession session;
|
||||||
|
private AbstractLoaderThread[] threads;
|
||||||
|
|
||||||
|
public FileFolderRemoteLoader(Properties properties, String username, String password)
|
||||||
|
{
|
||||||
|
this.properties = properties;
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void initialize() throws Exception
|
||||||
|
{
|
||||||
|
if (session != null || threads != null)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Application already initialized");
|
||||||
|
}
|
||||||
|
session = FileFolderRemoteLoader.makeSession(username, password, properties);
|
||||||
|
threads = FileFolderRemoteLoader.makeThreads(session, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void start()
|
||||||
|
{
|
||||||
|
if (session == null || threads == null)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Application not initialized");
|
||||||
|
}
|
||||||
|
// Fire up the threads
|
||||||
|
for (Thread thread : threads)
|
||||||
|
{
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void stop()
|
||||||
|
{
|
||||||
|
// Stop the threads
|
||||||
|
for (AbstractLoaderThread thread : threads)
|
||||||
|
{
|
||||||
|
thread.setStop();
|
||||||
|
}
|
||||||
|
// Now join each thread to make sure they all finish their current operation
|
||||||
|
for (AbstractLoaderThread thread : threads)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e) {}
|
||||||
|
}
|
||||||
|
// Get each one's summary
|
||||||
|
for (AbstractLoaderThread thread : threads)
|
||||||
|
{
|
||||||
|
String summary = thread.getSummary();
|
||||||
|
session.logNormal(summary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String PROP_SESSION_NAME = "session.name";
|
||||||
|
public static final String PROP_SESSION_VERBOSE = "session.verbose";
|
||||||
|
public static final String PROP_SESSION_SOURCE_DIR = "session.sourceDir";
|
||||||
|
public static final String PROP_SESSION_STORE_IDENTIFIERS = "session.storeIdentifiers";
|
||||||
|
public static final String PROP_SESSION_RMI_URLS = "session.rmiUrls";
|
||||||
|
public static final String PROP_SESSION_FOLDER_PROFILE = "session.folderProfile";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method to construct a session using the given properties.
|
||||||
|
*/
|
||||||
|
private static LoaderSession makeSession(String username, String password, Properties properties) throws Exception
|
||||||
|
{
|
||||||
|
// Name
|
||||||
|
String name = properties.getProperty(PROP_SESSION_NAME);
|
||||||
|
FileFolderRemoteLoader.checkProperty(PROP_SESSION_STORE_IDENTIFIERS, name);
|
||||||
|
|
||||||
|
// Verbose
|
||||||
|
String verboseStr = properties.getProperty(PROP_SESSION_VERBOSE);
|
||||||
|
boolean verbose = verboseStr == null ? false : Boolean.parseBoolean(verboseStr);
|
||||||
|
|
||||||
|
// Source files
|
||||||
|
String sourceDirStr = properties.getProperty(PROP_SESSION_SOURCE_DIR);
|
||||||
|
File sourceDir = new File(sourceDirStr);
|
||||||
|
|
||||||
|
// Stores
|
||||||
|
String storeIdentifiersStr = properties.getProperty(PROP_SESSION_STORE_IDENTIFIERS);
|
||||||
|
FileFolderRemoteLoader.checkProperty(PROP_SESSION_STORE_IDENTIFIERS, storeIdentifiersStr);
|
||||||
|
StringTokenizer tokenizer = new StringTokenizer(storeIdentifiersStr, ",");
|
||||||
|
Set<StoreRef> storeRefs = new HashSet<StoreRef>();
|
||||||
|
while (tokenizer.hasMoreTokens())
|
||||||
|
{
|
||||||
|
String storeIdentifier = tokenizer.nextToken().trim();
|
||||||
|
storeRefs.add(new StoreRef(STORE_PROTOCOL, storeIdentifier));
|
||||||
|
}
|
||||||
|
FileFolderRemoteLoader.checkProperty(PROP_SESSION_STORE_IDENTIFIERS, storeRefs);
|
||||||
|
|
||||||
|
// RMI URLs
|
||||||
|
String rmiUrlsStr = properties.getProperty(PROP_SESSION_RMI_URLS);
|
||||||
|
FileFolderRemoteLoader.checkProperty(PROP_SESSION_RMI_URLS, rmiUrlsStr);
|
||||||
|
tokenizer = new StringTokenizer(rmiUrlsStr, ",");
|
||||||
|
Set<String> rmiUrls = new HashSet<String>();
|
||||||
|
while (tokenizer.hasMoreTokens())
|
||||||
|
{
|
||||||
|
String rmiUrl = tokenizer.nextToken().trim();
|
||||||
|
rmiUrls.add(rmiUrl);
|
||||||
|
}
|
||||||
|
FileFolderRemoteLoader.checkProperty(PROP_SESSION_STORE_IDENTIFIERS, rmiUrls);
|
||||||
|
|
||||||
|
// RMI URLs
|
||||||
|
String folderProfilesStr = properties.getProperty(PROP_SESSION_FOLDER_PROFILE);
|
||||||
|
FileFolderRemoteLoader.checkProperty(PROP_SESSION_FOLDER_PROFILE, folderProfilesStr);
|
||||||
|
tokenizer = new StringTokenizer(folderProfilesStr, ",");
|
||||||
|
ArrayList<Integer> folderProfilesList = new ArrayList<Integer>(5);
|
||||||
|
while (tokenizer.hasMoreTokens())
|
||||||
|
{
|
||||||
|
String folderProfileStr = tokenizer.nextToken().trim();
|
||||||
|
Integer folderProfile = Integer.valueOf(folderProfileStr);
|
||||||
|
folderProfilesList.add(folderProfile);
|
||||||
|
}
|
||||||
|
FileFolderRemoteLoader.checkProperty(PROP_SESSION_FOLDER_PROFILE, folderProfilesList);
|
||||||
|
int[] folderProfiles = new int[folderProfilesList.size()];
|
||||||
|
for (int i = 0; i < folderProfiles.length; i++)
|
||||||
|
{
|
||||||
|
folderProfiles[i] = folderProfilesList.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct
|
||||||
|
LoaderSession session = new LoaderSession(
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
name,
|
||||||
|
rmiUrls,
|
||||||
|
storeRefs,
|
||||||
|
verbose,
|
||||||
|
sourceDir,
|
||||||
|
folderProfiles);
|
||||||
|
|
||||||
|
// Initialize the session
|
||||||
|
session.initialize();
|
||||||
|
|
||||||
|
// Done
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method to construct the worker threads.
|
||||||
|
*/
|
||||||
|
private static AbstractLoaderThread[] makeThreads(LoaderSession session, Properties properties) throws Exception
|
||||||
|
{
|
||||||
|
ArrayList<AbstractLoaderThread> threads = new ArrayList<AbstractLoaderThread>(3);
|
||||||
|
// Iterate over the properties and pick out the thread descriptors
|
||||||
|
for (String propertyName : properties.stringPropertyNames())
|
||||||
|
{
|
||||||
|
if (!propertyName.startsWith("test.load."))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String name = propertyName;
|
||||||
|
|
||||||
|
// Get the type of the test
|
||||||
|
int lastIndex = propertyName.indexOf(".", 10);
|
||||||
|
if (lastIndex < 0)
|
||||||
|
{
|
||||||
|
throw new LoaderClientException(
|
||||||
|
"Invalid test loader property. " +
|
||||||
|
"It should be of the form 'test.load.upload.xyz=...': " + propertyName);
|
||||||
|
}
|
||||||
|
String type = propertyName.substring(10, lastIndex);
|
||||||
|
|
||||||
|
// Get the values
|
||||||
|
String valuesStr = properties.getProperty(propertyName);
|
||||||
|
FileFolderRemoteLoader.checkProperty(propertyName, valuesStr);
|
||||||
|
// Parse it into the well-known values
|
||||||
|
int[] values = new int[] {1, 0, -1, 1};
|
||||||
|
int index = 0;
|
||||||
|
StringTokenizer tokenizer = new StringTokenizer(valuesStr, ",");
|
||||||
|
while (tokenizer.hasMoreTokens())
|
||||||
|
{
|
||||||
|
String value = tokenizer.nextToken().trim();
|
||||||
|
values[index] = Integer.parseInt(value);
|
||||||
|
index++;
|
||||||
|
if (index >= values.length)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int testCount = values[0];
|
||||||
|
int testPeriod = values[1];
|
||||||
|
int testTotal = values[2];
|
||||||
|
int testDepth = values[3];
|
||||||
|
|
||||||
|
// Construct
|
||||||
|
for (int i = 0; i < testCount; i++)
|
||||||
|
{
|
||||||
|
AbstractLoaderThread thread = null;
|
||||||
|
if (type.equals("upload"))
|
||||||
|
{
|
||||||
|
thread = new LoaderUploadThread(session, name, testPeriod, testTotal, testDepth);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new LoaderClientException("Unknown test type: " + name);
|
||||||
|
}
|
||||||
|
threads.add(thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Done
|
||||||
|
AbstractLoaderThread[] ret = new AbstractLoaderThread[threads.size()];
|
||||||
|
return threads.toArray(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for null values and empty collections.
|
||||||
|
*/
|
||||||
|
private static void checkProperty(String propertyName, Object propertyValue) throws LoaderClientException
|
||||||
|
{
|
||||||
|
if (propertyValue == null)
|
||||||
|
{
|
||||||
|
throw new LoaderClientException("'" + propertyName + "' must be provided.");
|
||||||
|
}
|
||||||
|
else if (propertyValue instanceof Collection)
|
||||||
|
{
|
||||||
|
Collection propertyCollection = (Collection) propertyValue;
|
||||||
|
int size = propertyCollection.size();
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
throw new LoaderClientException("'" + propertyName + "' does not have any values.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String ... args)
|
||||||
|
{
|
||||||
|
Map<String, String> argMap = ripArgs(args);
|
||||||
|
String username = argMap.get("username");
|
||||||
|
String password = argMap.get("password");
|
||||||
|
String config = argMap.get("config");
|
||||||
|
if (username == null || password == null || config == null)
|
||||||
|
{
|
||||||
|
printUsage();
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File propertiesFile = new File(config);
|
||||||
|
if (!propertiesFile.exists())
|
||||||
|
{
|
||||||
|
System.err.println("Unable to find config file: " + config);
|
||||||
|
}
|
||||||
|
Properties properties = new Properties();
|
||||||
|
properties.load(new FileInputStream(propertiesFile));
|
||||||
|
|
||||||
|
FileFolderRemoteLoader app = new FileFolderRemoteLoader(properties, username, password);
|
||||||
|
|
||||||
|
// Initialize
|
||||||
|
app.initialize();
|
||||||
|
|
||||||
|
// Run
|
||||||
|
app.start();
|
||||||
|
|
||||||
|
synchronized(app)
|
||||||
|
{
|
||||||
|
app.wait(1000L);
|
||||||
|
}
|
||||||
|
// System.out.println(""
|
||||||
|
|
||||||
|
// Finish off
|
||||||
|
app.stop();
|
||||||
|
}
|
||||||
|
catch (LoaderClientException e)
|
||||||
|
{
|
||||||
|
System.err.println(e.getMessage());
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
System.err.println("A failure prevented proper execution.");
|
||||||
|
e.printStackTrace();
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> ripArgs(String ... args)
|
||||||
|
{
|
||||||
|
Map<String, String> argsMap = new HashMap<String, String>(5);
|
||||||
|
for (String arg : args)
|
||||||
|
{
|
||||||
|
int index = arg.indexOf('=');
|
||||||
|
if (!arg.startsWith("--") || index < 0 || index == arg.length() - 1)
|
||||||
|
{
|
||||||
|
// Ignore it
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String name = arg.substring(2, index);
|
||||||
|
String value = arg.substring(index + 1, arg.length());
|
||||||
|
argsMap.put(name, value);
|
||||||
|
}
|
||||||
|
return argsMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void printUsage()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("\n")
|
||||||
|
.append("Usage\n")
|
||||||
|
.append(" java -jar ... --username=<username> --password=<password> --config=<config file> \n");
|
||||||
|
System.out.println(sb.toString());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.model.filefolder.loader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to catch non-critical issues.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public class LoaderClientException extends Exception
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = -3306363763048881956L;
|
||||||
|
|
||||||
|
public LoaderClientException(String msg)
|
||||||
|
{
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.model.filefolder.loader;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.remote.FileFolderRemote;
|
||||||
|
import org.alfresco.service.cmr.remote.LoaderRemote;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to store remote service connections.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public class LoaderServerProxy
|
||||||
|
{
|
||||||
|
public final String rmiUrl;
|
||||||
|
public final String ticket;
|
||||||
|
public final FileFolderRemote fileFolderRemote;
|
||||||
|
public final LoaderRemote loaderRemote;
|
||||||
|
|
||||||
|
public LoaderServerProxy(
|
||||||
|
String rmiUrl,
|
||||||
|
String ticket,
|
||||||
|
FileFolderRemote fileFolderRemote,
|
||||||
|
LoaderRemote loaderRemote)
|
||||||
|
{
|
||||||
|
this.rmiUrl = rmiUrl;
|
||||||
|
this.ticket = ticket;
|
||||||
|
this.fileFolderRemote = fileFolderRemote;
|
||||||
|
this.loaderRemote = loaderRemote;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,386 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.model.filefolder.loader;
|
||||||
|
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.remote.FileFolderRemoteClient;
|
||||||
|
import org.alfresco.service.cmr.model.FileInfo;
|
||||||
|
import org.alfresco.service.cmr.remote.LoaderRemote;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
import org.springframework.remoting.rmi.RmiProxyFactoryBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A description of session details.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
* @since 2.2
|
||||||
|
*/
|
||||||
|
public class LoaderSession
|
||||||
|
{
|
||||||
|
public static final ThreadGroup THREAD_GROUP = new ThreadGroup("FileFolderRemoteLoader");
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
private String name;
|
||||||
|
private Set<String> rmiUrls;
|
||||||
|
private Set<StoreRef> storeRefs;
|
||||||
|
private boolean verbose;
|
||||||
|
private File outputFile;
|
||||||
|
private File sourceDir;
|
||||||
|
private int[] folderProfiles;
|
||||||
|
|
||||||
|
private List<LoaderServerProxy> remoteServers;
|
||||||
|
private List<NodeRef> workingRootNodeRefs;
|
||||||
|
private File[] sourceFiles;
|
||||||
|
private OutputStream outStream;
|
||||||
|
private OutputStream errStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public LoaderSession(
|
||||||
|
String username,
|
||||||
|
String password,
|
||||||
|
String name,
|
||||||
|
Set<String> rmiUrls,
|
||||||
|
Set<StoreRef> storeRefs,
|
||||||
|
boolean verbose,
|
||||||
|
File sourceDir,
|
||||||
|
int[] folderProfiles)
|
||||||
|
{
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
this.name = name;
|
||||||
|
this.rmiUrls = rmiUrls;
|
||||||
|
this.storeRefs = storeRefs;
|
||||||
|
this.verbose = verbose;
|
||||||
|
this.sourceDir = sourceDir;
|
||||||
|
this.folderProfiles = folderProfiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<LoaderServerProxy> getRemoteServers()
|
||||||
|
{
|
||||||
|
return remoteServers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<NodeRef> getWorkingRootNodeRefs()
|
||||||
|
{
|
||||||
|
return workingRootNodeRefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File[] getSourceFiles()
|
||||||
|
{
|
||||||
|
return sourceFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] getFolderProfiles()
|
||||||
|
{
|
||||||
|
return folderProfiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the object before first use.
|
||||||
|
*/
|
||||||
|
public synchronized void initialize() throws Exception
|
||||||
|
{
|
||||||
|
if (remoteServers != null)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("The client has already been initialized");
|
||||||
|
}
|
||||||
|
remoteServers = LoaderSession.connect(rmiUrls, username, password);
|
||||||
|
workingRootNodeRefs = LoaderSession.makeStores(remoteServers, storeRefs);
|
||||||
|
LoaderSession.checkClustering(remoteServers, workingRootNodeRefs);
|
||||||
|
|
||||||
|
// Create the output file, if necessary
|
||||||
|
if (outputFile != null)
|
||||||
|
{
|
||||||
|
File outputDir = outputFile.getParentFile();
|
||||||
|
if (!outputDir.exists())
|
||||||
|
{
|
||||||
|
outputDir.mkdirs();
|
||||||
|
}
|
||||||
|
if (outputFile.exists())
|
||||||
|
{
|
||||||
|
System.out.println("The output file " + outputFile + " already exists.");
|
||||||
|
System.out.println("Are you sure you want to overwrite the file?");
|
||||||
|
int in = System.in.read();
|
||||||
|
if (in != 'Y' && in != 'y')
|
||||||
|
{
|
||||||
|
throw new LoaderClientException("The output file " + outputFile + " already exists");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the source files
|
||||||
|
sourceFiles = LoaderSession.getSourceFiles(sourceDir);
|
||||||
|
|
||||||
|
// Construct output and error files
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
File outFile = new File("./LoaderSession-" + name + "-"+ time + "-out.txt");
|
||||||
|
File errFile = new File("./LoaderSession-" + name + "-"+ time + "-err.txt");
|
||||||
|
outStream = new BufferedOutputStream(new FileOutputStream(outFile));
|
||||||
|
errStream = new BufferedOutputStream(new FileOutputStream(errFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void close()
|
||||||
|
{
|
||||||
|
try { outStream.close(); } catch (Throwable e) {}
|
||||||
|
try { errStream.close(); } catch (Throwable e) {}
|
||||||
|
|
||||||
|
outStream = null;
|
||||||
|
errStream = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to the remote servers.
|
||||||
|
*/
|
||||||
|
private static List<LoaderServerProxy> connect(Set<String> rmiUrls, String username, String password) throws Exception
|
||||||
|
{
|
||||||
|
List<LoaderServerProxy> remoteServers = new ArrayList<LoaderServerProxy>(rmiUrls.size());
|
||||||
|
for (String rmiUrl : rmiUrls)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Ensure the RMI URL is consistent
|
||||||
|
if (!rmiUrl.endsWith("/"))
|
||||||
|
{
|
||||||
|
rmiUrl += "/";
|
||||||
|
}
|
||||||
|
// Get the FileFolderServiceTransport
|
||||||
|
FileFolderRemoteClient fileFolderRemote = new FileFolderRemoteClient(rmiUrl);
|
||||||
|
// Get the LoaderServiceTransport
|
||||||
|
RmiProxyFactoryBean loaderFactory = new RmiProxyFactoryBean();
|
||||||
|
loaderFactory.setRefreshStubOnConnectFailure(true);
|
||||||
|
loaderFactory.setServiceInterface(LoaderRemote.class);
|
||||||
|
loaderFactory.setServiceUrl(rmiUrl + LoaderRemote.SERVICE_NAME);
|
||||||
|
loaderFactory.afterPropertiesSet();
|
||||||
|
LoaderRemote loaderRemote = (LoaderRemote) loaderFactory.getObject();
|
||||||
|
|
||||||
|
// Authenticate
|
||||||
|
String ticket = loaderRemote.authenticate(username, password);
|
||||||
|
|
||||||
|
// Store the service references
|
||||||
|
LoaderServerProxy remoteServer = new LoaderServerProxy(
|
||||||
|
rmiUrl,
|
||||||
|
ticket,
|
||||||
|
fileFolderRemote,
|
||||||
|
loaderRemote);
|
||||||
|
remoteServers.add(remoteServer);
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
// Failed to connect.
|
||||||
|
System.err.println("\n" +
|
||||||
|
"ERROR: Failed to establish connection to server: \n" +
|
||||||
|
" Server: " + rmiUrl + "\n" +
|
||||||
|
" Error: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check that there is at least one server
|
||||||
|
if (remoteServers.size() == 0)
|
||||||
|
{
|
||||||
|
throw new LoaderClientException("No remote servers are available");
|
||||||
|
}
|
||||||
|
return remoteServers;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<NodeRef> makeStores(List<LoaderServerProxy> remoteServers, Set<StoreRef> storeRefs) throws Exception
|
||||||
|
{
|
||||||
|
// Take the first server and ensure that all the stores are available
|
||||||
|
LoaderServerProxy remoteServer = remoteServers.get(0);
|
||||||
|
|
||||||
|
List<NodeRef> workingRootNodeRefs = new ArrayList<NodeRef>(10);
|
||||||
|
for (StoreRef storeRef : storeRefs)
|
||||||
|
{
|
||||||
|
NodeRef workingRootNodeRef = remoteServer.loaderRemote.getOrCreateWorkingRoot(remoteServer.ticket, storeRef);
|
||||||
|
workingRootNodeRefs.add(workingRootNodeRef);
|
||||||
|
}
|
||||||
|
// Done
|
||||||
|
return workingRootNodeRefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void checkClustering(
|
||||||
|
List<LoaderServerProxy> remoteServers,
|
||||||
|
List<NodeRef> workingRootNodeRefs) throws Exception
|
||||||
|
{
|
||||||
|
List<String> problems = new ArrayList<String>(10);
|
||||||
|
for (LoaderServerProxy remoteServer : remoteServers)
|
||||||
|
{
|
||||||
|
String ticket = remoteServer.ticket;
|
||||||
|
for (NodeRef workingRootNodeRef : workingRootNodeRefs)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Get the working root node. If the cluster is correctly configured,
|
||||||
|
// it will be available on all the servers.
|
||||||
|
FileInfo fileInfo = remoteServer.fileFolderRemote.getFileInfo(ticket, workingRootNodeRef);
|
||||||
|
if (fileInfo == null)
|
||||||
|
{
|
||||||
|
problems.add("Cannot find the working root node on server: " + remoteServer.rmiUrl);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Now look for and create a file against which to store some content
|
||||||
|
String sampleFilename = "InitialSample.txt";
|
||||||
|
String sampleContent = "Sample content";
|
||||||
|
NodeRef sampleNodeRef = remoteServer.fileFolderRemote.searchSimple(ticket, workingRootNodeRef, sampleFilename);
|
||||||
|
if (sampleNodeRef == null)
|
||||||
|
{
|
||||||
|
FileInfo sampleFileInfo = remoteServer.fileFolderRemote.create(
|
||||||
|
ticket, workingRootNodeRef, sampleFilename, ContentModel.TYPE_CONTENT);
|
||||||
|
sampleNodeRef = sampleFileInfo.getNodeRef();
|
||||||
|
// Write some content
|
||||||
|
byte[] bytes = sampleContent.getBytes("UTF-8");
|
||||||
|
remoteServer.fileFolderRemote.putContent(ticket, sampleNodeRef, bytes, sampleFilename);
|
||||||
|
}
|
||||||
|
// Get the content and ensure that it is the same
|
||||||
|
byte[] bytes = remoteServer.fileFolderRemote.getContent(ticket, sampleNodeRef);
|
||||||
|
if (bytes == null)
|
||||||
|
{
|
||||||
|
problems.add("Sample content was not found on server: " + remoteServer.rmiUrl);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String checkContent = new String(bytes, "UTF-8");
|
||||||
|
if (!checkContent.equals(sampleContent))
|
||||||
|
{
|
||||||
|
problems.add("The sample content differed from expected: " + remoteServer.rmiUrl);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
System.err.println("ERROR: Failure whilst checking server: " + remoteServer.rmiUrl);
|
||||||
|
e.printStackTrace();
|
||||||
|
problems.add(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check for issues
|
||||||
|
if (problems.size() > 0)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("\n")
|
||||||
|
.append("The working root node references could not be found on all the remote servers.\n")
|
||||||
|
.append("Please ensure that all the remote servers listed are active in a single cluster.");
|
||||||
|
for (String problem : problems)
|
||||||
|
{
|
||||||
|
sb.append("\n")
|
||||||
|
.append(" ").append(problem);
|
||||||
|
}
|
||||||
|
throw new LoaderClientException(sb.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static File[] getSourceFiles(File sourceDir) throws Exception
|
||||||
|
{
|
||||||
|
// Ensure that the source directory is present, if specified
|
||||||
|
if (sourceDir != null)
|
||||||
|
{
|
||||||
|
if (!sourceDir.exists())
|
||||||
|
{
|
||||||
|
throw new LoaderClientException("The source directory to contain upload files is missing: " + sourceDir);
|
||||||
|
}
|
||||||
|
// Check that there is something in it
|
||||||
|
File[] allFiles = sourceDir.listFiles();
|
||||||
|
ArrayList<File> sourceFiles = new ArrayList<File>(allFiles.length);
|
||||||
|
for (File file : allFiles)
|
||||||
|
{
|
||||||
|
if (file.isDirectory())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sourceFiles.add(file);
|
||||||
|
}
|
||||||
|
File[] ret = new File[sourceFiles.size()];
|
||||||
|
return sourceFiles.toArray(ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new File[] {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logVerbose(String msg)
|
||||||
|
{
|
||||||
|
if (!verbose)
|
||||||
|
{
|
||||||
|
// Just ignore it
|
||||||
|
}
|
||||||
|
logNormal(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void logNormal(String msg)
|
||||||
|
{
|
||||||
|
if (outStream == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] bytes = msg.getBytes("UTF-8");
|
||||||
|
outStream.write(bytes);
|
||||||
|
outStream.write('\n');
|
||||||
|
outStream.flush();
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
System.err.println("Failed to write message to output file: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void logError(String msg)
|
||||||
|
{
|
||||||
|
if (errStream == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] bytes = msg.getBytes("UTF-8");
|
||||||
|
errStream.write(bytes);
|
||||||
|
outStream.write('\n');
|
||||||
|
errStream.flush();
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
System.err.println("Failed to write message to output file: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.model.filefolder.loader;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A description of what the remote loader should do.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public class LoaderUploadThread extends AbstractLoaderThread
|
||||||
|
{
|
||||||
|
public LoaderUploadThread(
|
||||||
|
LoaderSession session,
|
||||||
|
String loaderName,
|
||||||
|
int testPeriod,
|
||||||
|
int testTotal,
|
||||||
|
int testLoadDepth)
|
||||||
|
{
|
||||||
|
super(session, loaderName, testPeriod, testTotal, testLoadDepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doLoading(LoaderServerProxy serverProxy, NodeRef workingRootNodeRef) throws Exception
|
||||||
|
{
|
||||||
|
int totalNodeCount = serverProxy.loaderRemote.getNodeCount(
|
||||||
|
serverProxy.ticket);
|
||||||
|
int storeNodeCount = serverProxy.loaderRemote.getNodeCount(
|
||||||
|
serverProxy.ticket,
|
||||||
|
workingRootNodeRef.getStoreRef());
|
||||||
|
session.logVerbose("Nodes: " + totalNodeCount + ". Store Nodes: " + storeNodeCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSummary()
|
||||||
|
{
|
||||||
|
return "Tanker";
|
||||||
|
}
|
||||||
|
}
|
@@ -284,6 +284,15 @@ public interface NodeDaoService
|
|||||||
*/
|
*/
|
||||||
public List<Serializable> getPropertyValuesByActualType(DataTypeDefinition actualDataTypeDefinition);
|
public List<Serializable> getPropertyValuesByActualType(DataTypeDefinition actualDataTypeDefinition);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the total number of nodes in the ADM repository
|
||||||
|
*/
|
||||||
|
public int getNodeCount();
|
||||||
|
/**
|
||||||
|
* @return Returns the total number of nodes in the ADM store
|
||||||
|
*/
|
||||||
|
public int getNodeCount(final StoreRef storeRef);
|
||||||
|
|
||||||
public Transaction getTxnById(long txnId);
|
public Transaction getTxnById(long txnId);
|
||||||
public Transaction getLastTxn();
|
public Transaction getLastTxn();
|
||||||
public Transaction getLastRemoteTxn();
|
public Transaction getLastRemoteTxn();
|
||||||
|
@@ -106,6 +106,9 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
|||||||
private static final String QUERY_GET_NODES_WITH_PROPERTY_VALUES_BY_ACTUAL_TYPE = "node.GetNodesWithPropertyValuesByActualType";
|
private static final String QUERY_GET_NODES_WITH_PROPERTY_VALUES_BY_ACTUAL_TYPE = "node.GetNodesWithPropertyValuesByActualType";
|
||||||
private static final String QUERY_GET_SERVER_BY_IPADDRESS = "server.getServerByIpAddress";
|
private static final String QUERY_GET_SERVER_BY_IPADDRESS = "server.getServerByIpAddress";
|
||||||
|
|
||||||
|
private static final String QUERY_GET_NODE_COUNT = "node.GetNodeCount";
|
||||||
|
private static final String QUERY_GET_NODE_COUNT_FOR_STORE = "node.GetNodeCountForStore";
|
||||||
|
|
||||||
private static final String QUERY_GET_NODE_STATUSES_FOR_STORE = "node.GetNodeStatusesForStore";
|
private static final String QUERY_GET_NODE_STATUSES_FOR_STORE = "node.GetNodeStatusesForStore";
|
||||||
private static final String QUERY_GET_CHILD_ASSOCS_FOR_STORE = "node.GetChildAssocsForStore";
|
private static final String QUERY_GET_CHILD_ASSOCS_FOR_STORE = "node.GetChildAssocsForStore";
|
||||||
private static final String QUERY_GET_NODES_EXCEPT_ROOT_FOR_STORE = "node.GetNodesExceptRootForStore";
|
private static final String QUERY_GET_NODES_EXCEPT_ROOT_FOR_STORE = "node.GetNodesExceptRootForStore";
|
||||||
@@ -367,6 +370,7 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
|||||||
* @param protocol the store protocol
|
* @param protocol the store protocol
|
||||||
* @param identifier the store identifier
|
* @param identifier the store identifier
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public void deleteStore(final String protocol, final String identifier)
|
public void deleteStore(final String protocol, final String identifier)
|
||||||
{
|
{
|
||||||
// ensure that the store exists
|
// ensure that the store exists
|
||||||
@@ -1368,6 +1372,48 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
|||||||
return convertedValues;
|
return convertedValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public int getNodeCount()
|
||||||
|
{
|
||||||
|
HibernateCallback callback = new HibernateCallback()
|
||||||
|
{
|
||||||
|
public Object doInHibernate(Session session)
|
||||||
|
{
|
||||||
|
Query query = session.getNamedQuery(QUERY_GET_NODE_COUNT);
|
||||||
|
query.setMaxResults(1)
|
||||||
|
.setReadOnly(true);
|
||||||
|
return query.uniqueResult();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Long count = (Long) getHibernateTemplate().execute(callback);
|
||||||
|
// done
|
||||||
|
return count.intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public int getNodeCount(final StoreRef storeRef)
|
||||||
|
{
|
||||||
|
HibernateCallback callback = new HibernateCallback()
|
||||||
|
{
|
||||||
|
public Object doInHibernate(Session session)
|
||||||
|
{
|
||||||
|
Query query = session.getNamedQuery(QUERY_GET_NODE_COUNT_FOR_STORE);
|
||||||
|
query.setString("protocol", storeRef.getProtocol())
|
||||||
|
.setString("identifier", storeRef.getIdentifier())
|
||||||
|
.setMaxResults(1)
|
||||||
|
.setReadOnly(true);
|
||||||
|
return query.uniqueResult();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Long count = (Long) getHibernateTemplate().execute(callback);
|
||||||
|
// done
|
||||||
|
return count.intValue();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Queries for transactions
|
* Queries for transactions
|
||||||
*/
|
*/
|
||||||
|
239
source/java/org/alfresco/repo/remote/FileFolderRemoteClient.java
Normal file
239
source/java/org/alfresco/repo/remote/FileFolderRemoteClient.java
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.remote;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.model.FileExistsException;
|
||||||
|
import org.alfresco.service.cmr.model.FileInfo;
|
||||||
|
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||||
|
import org.alfresco.service.cmr.remote.FileFolderRemote;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentData;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.springframework.remoting.rmi.RmiProxyFactoryBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client side implementation of the remotable FileFolder interface.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
* @since 2.2
|
||||||
|
*/
|
||||||
|
public class FileFolderRemoteClient implements FileFolderRemote
|
||||||
|
{
|
||||||
|
private String rmiUrl;
|
||||||
|
private FileFolderRemote remotePeer;
|
||||||
|
|
||||||
|
public FileFolderRemoteClient(String rmiUrl)
|
||||||
|
{
|
||||||
|
// Ensure the RMI URL is consistent
|
||||||
|
if (!rmiUrl.endsWith("/"))
|
||||||
|
{
|
||||||
|
rmiUrl += "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
this.rmiUrl = rmiUrl;
|
||||||
|
// Connect
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void connect()
|
||||||
|
{
|
||||||
|
// Get the FileFolderServiceTransport
|
||||||
|
RmiProxyFactoryBean fileFolderFactory = new RmiProxyFactoryBean();
|
||||||
|
fileFolderFactory.setRefreshStubOnConnectFailure(true);
|
||||||
|
fileFolderFactory.setServiceInterface(FileFolderRemote.class);
|
||||||
|
fileFolderFactory.setServiceUrl(rmiUrl + FileFolderRemote.SERVICE_NAME);
|
||||||
|
fileFolderFactory.afterPropertiesSet();
|
||||||
|
FileFolderRemote fileFolderRemote = (FileFolderRemote) fileFolderFactory.getObject();
|
||||||
|
this.remotePeer = fileFolderRemote;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public List<FileInfo> list(String ticket, final NodeRef contextNodeRef)
|
||||||
|
{
|
||||||
|
return remotePeer.list(ticket, contextNodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public List<FileInfo> listFiles(String ticket, final NodeRef folderNodeRef)
|
||||||
|
{
|
||||||
|
return remotePeer.listFiles(ticket, folderNodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public List<FileInfo> listFolders(String ticket, final NodeRef contextNodeRef)
|
||||||
|
{
|
||||||
|
return remotePeer.listFolders(ticket, contextNodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public NodeRef searchSimple(String ticket, final NodeRef contextNodeRef, final String name)
|
||||||
|
{
|
||||||
|
return remotePeer.searchSimple(ticket, contextNodeRef, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public List<FileInfo> search(
|
||||||
|
String ticket,
|
||||||
|
final NodeRef contextNodeRef,
|
||||||
|
final String namePattern,
|
||||||
|
final boolean includeSubFolders)
|
||||||
|
{
|
||||||
|
return remotePeer.search(ticket, contextNodeRef, namePattern, includeSubFolders);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public List<FileInfo> search(
|
||||||
|
String ticket,
|
||||||
|
final NodeRef contextNodeRef,
|
||||||
|
final String namePattern,
|
||||||
|
final boolean fileSearch,
|
||||||
|
final boolean folderSearch,
|
||||||
|
final boolean includeSubFolders)
|
||||||
|
{
|
||||||
|
return remotePeer.search(ticket, contextNodeRef, namePattern, fileSearch, folderSearch, includeSubFolders);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public FileInfo rename(String ticket, final NodeRef fileFolderRef, final String newName) throws FileExistsException, FileNotFoundException
|
||||||
|
{
|
||||||
|
return remotePeer.rename(ticket, fileFolderRef, newName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public FileInfo move(String ticket, final NodeRef sourceNodeRef, final NodeRef targetParentRef, final String newName)
|
||||||
|
throws FileExistsException, FileNotFoundException
|
||||||
|
{
|
||||||
|
return remotePeer.move(ticket, sourceNodeRef, targetParentRef, newName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public FileInfo copy(String ticket, final NodeRef sourceNodeRef, final NodeRef targetParentRef, final String newName)
|
||||||
|
throws FileExistsException, FileNotFoundException
|
||||||
|
{
|
||||||
|
return remotePeer.copy(ticket, sourceNodeRef, targetParentRef, newName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public FileInfo create(String ticket, final NodeRef parentNodeRef, final String name, final QName typeQName) throws FileExistsException
|
||||||
|
{
|
||||||
|
return remotePeer.create(ticket, parentNodeRef, name, typeQName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public void delete(String ticket, final NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
remotePeer.delete(ticket, nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public FileInfo makeFolders(String ticket, final NodeRef parentNodeRef, final List<String> pathElements, final QName folderTypeQName)
|
||||||
|
{
|
||||||
|
return remotePeer.makeFolders(ticket, parentNodeRef, pathElements, folderTypeQName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public List<FileInfo> getNamePath(String ticket, final NodeRef rootNodeRef, final NodeRef nodeRef) throws FileNotFoundException
|
||||||
|
{
|
||||||
|
return remotePeer.getNamePath(ticket, rootNodeRef, nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public FileInfo resolveNamePath(String ticket, final NodeRef rootNodeRef, final List<String> pathElements) throws FileNotFoundException
|
||||||
|
{
|
||||||
|
return remotePeer.resolveNamePath(ticket, rootNodeRef, pathElements);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public FileInfo getFileInfo(String ticket, final NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
return remotePeer.getFileInfo(ticket, nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public ContentData putContent(String ticket, NodeRef nodeRef, byte[] bytes, String filename)
|
||||||
|
{
|
||||||
|
return remotePeer.putContent(ticket, nodeRef, bytes, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public byte[] getContent(String ticket, NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
return remotePeer.getContent(ticket, nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public ContentReader getReader(String ticket, NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public ContentWriter getWriter(String ticket, NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
591
source/java/org/alfresco/repo/remote/FileFolderRemoteServer.java
Normal file
591
source/java/org/alfresco/repo/remote/FileFolderRemoteServer.java
Normal file
@@ -0,0 +1,591 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.remote;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.sf.acegisecurity.Authentication;
|
||||||
|
|
||||||
|
import org.alfresco.repo.content.encoding.ContentCharsetFinder;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
|
import org.alfresco.service.cmr.model.FileExistsException;
|
||||||
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
|
import org.alfresco.service.cmr.model.FileInfo;
|
||||||
|
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||||
|
import org.alfresco.service.cmr.remote.FileFolderRemote;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentData;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
|
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server side implementation of the <code>FileFolderService</code> transport
|
||||||
|
* layer. This is the class that gets exported remotely as it contains the
|
||||||
|
* explicit ticket arguments.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
* @since 2.2
|
||||||
|
*/
|
||||||
|
public class FileFolderRemoteServer implements FileFolderRemote
|
||||||
|
{
|
||||||
|
private RetryingTransactionHelper retryingTransactionHelper;
|
||||||
|
private AuthenticationService authenticationService;
|
||||||
|
private FileFolderService fileFolderService;
|
||||||
|
private MimetypeService mimetypeService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param transactionService provides transactional support and retrying
|
||||||
|
*/
|
||||||
|
public void setTransactionService(TransactionService transactionService)
|
||||||
|
{
|
||||||
|
this.retryingTransactionHelper = transactionService.getRetryingTransactionHelper();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param authenticationService the service that will validate the tickets
|
||||||
|
*/
|
||||||
|
public void setAuthenticationService(AuthenticationService authenticationService)
|
||||||
|
{
|
||||||
|
this.authenticationService = authenticationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param filefolderService the service that will do the work
|
||||||
|
*/
|
||||||
|
public void setFileFolderService(FileFolderService filefolderService)
|
||||||
|
{
|
||||||
|
this.fileFolderService = filefolderService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mimetypeService used to determine the character encoding
|
||||||
|
*/
|
||||||
|
public void setMimetypeService(MimetypeService mimetypeService)
|
||||||
|
{
|
||||||
|
this.mimetypeService = mimetypeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public List<FileInfo> list(String ticket, final NodeRef contextNodeRef)
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<List<FileInfo>> callback = new RetryingTransactionCallback<List<FileInfo>>()
|
||||||
|
{
|
||||||
|
public List<FileInfo> execute() throws Throwable
|
||||||
|
{
|
||||||
|
return fileFolderService.list(contextNodeRef);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public List<FileInfo> listFiles(String ticket, final NodeRef folderNodeRef)
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<List<FileInfo>> callback = new RetryingTransactionCallback<List<FileInfo>>()
|
||||||
|
{
|
||||||
|
public List<FileInfo> execute() throws Throwable
|
||||||
|
{
|
||||||
|
return fileFolderService.listFiles(folderNodeRef);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public List<FileInfo> listFolders(String ticket, final NodeRef contextNodeRef)
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<List<FileInfo>> callback = new RetryingTransactionCallback<List<FileInfo>>()
|
||||||
|
{
|
||||||
|
public List<FileInfo> execute() throws Throwable
|
||||||
|
{
|
||||||
|
return fileFolderService.listFolders(contextNodeRef);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public NodeRef searchSimple(String ticket, final NodeRef contextNodeRef, final String name)
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<NodeRef> callback = new RetryingTransactionCallback<NodeRef>()
|
||||||
|
{
|
||||||
|
public NodeRef execute() throws Throwable
|
||||||
|
{
|
||||||
|
return fileFolderService.searchSimple(contextNodeRef, name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public List<FileInfo> search(
|
||||||
|
String ticket,
|
||||||
|
final NodeRef contextNodeRef,
|
||||||
|
final String namePattern,
|
||||||
|
final boolean includeSubFolders)
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<List<FileInfo>> callback = new RetryingTransactionCallback<List<FileInfo>>()
|
||||||
|
{
|
||||||
|
public List<FileInfo> execute() throws Throwable
|
||||||
|
{
|
||||||
|
return fileFolderService.search(contextNodeRef, namePattern, includeSubFolders);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public List<FileInfo> search(
|
||||||
|
String ticket,
|
||||||
|
final NodeRef contextNodeRef,
|
||||||
|
final String namePattern,
|
||||||
|
final boolean fileSearch,
|
||||||
|
final boolean folderSearch,
|
||||||
|
final boolean includeSubFolders)
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<List<FileInfo>> callback = new RetryingTransactionCallback<List<FileInfo>>()
|
||||||
|
{
|
||||||
|
public List<FileInfo> execute() throws Throwable
|
||||||
|
{
|
||||||
|
return fileFolderService.search(contextNodeRef, namePattern, fileSearch, folderSearch, includeSubFolders);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public FileInfo rename(String ticket, final NodeRef fileFolderRef, final String newName) throws FileExistsException, FileNotFoundException
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<FileInfo> callback = new RetryingTransactionCallback<FileInfo>()
|
||||||
|
{
|
||||||
|
public FileInfo execute() throws Throwable
|
||||||
|
{
|
||||||
|
return fileFolderService.rename(fileFolderRef, newName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return retryingTransactionHelper.doInTransaction(callback, false, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public FileInfo move(String ticket, final NodeRef sourceNodeRef, final NodeRef targetParentRef, final String newName)
|
||||||
|
throws FileExistsException, FileNotFoundException
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<FileInfo> callback = new RetryingTransactionCallback<FileInfo>()
|
||||||
|
{
|
||||||
|
public FileInfo execute() throws Throwable
|
||||||
|
{
|
||||||
|
return fileFolderService.move(sourceNodeRef, targetParentRef, newName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return retryingTransactionHelper.doInTransaction(callback, false, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public FileInfo copy(String ticket, final NodeRef sourceNodeRef, final NodeRef targetParentRef, final String newName)
|
||||||
|
throws FileExistsException, FileNotFoundException
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<FileInfo> callback = new RetryingTransactionCallback<FileInfo>()
|
||||||
|
{
|
||||||
|
public FileInfo execute() throws Throwable
|
||||||
|
{
|
||||||
|
return fileFolderService.copy(sourceNodeRef, targetParentRef, newName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return retryingTransactionHelper.doInTransaction(callback, false, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public FileInfo create(String ticket, final NodeRef parentNodeRef, final String name, final QName typeQName) throws FileExistsException
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<FileInfo> callback = new RetryingTransactionCallback<FileInfo>()
|
||||||
|
{
|
||||||
|
public FileInfo execute() throws Throwable
|
||||||
|
{
|
||||||
|
return fileFolderService.create(parentNodeRef, name, typeQName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return retryingTransactionHelper.doInTransaction(callback, false, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public void delete(String ticket, final NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<Object> callback = new RetryingTransactionCallback<Object>()
|
||||||
|
{
|
||||||
|
public Object execute() throws Throwable
|
||||||
|
{
|
||||||
|
fileFolderService.delete(nodeRef);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
retryingTransactionHelper.doInTransaction(callback, false, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public FileInfo makeFolders(String ticket, final NodeRef parentNodeRef, final List<String> pathElements, final QName folderTypeQName)
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<FileInfo> callback = new RetryingTransactionCallback<FileInfo>()
|
||||||
|
{
|
||||||
|
public FileInfo execute() throws Throwable
|
||||||
|
{
|
||||||
|
return fileFolderService.makeFolders(parentNodeRef, pathElements, folderTypeQName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return retryingTransactionHelper.doInTransaction(callback, false, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public List<FileInfo> getNamePath(String ticket, final NodeRef rootNodeRef, final NodeRef nodeRef) throws FileNotFoundException
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<List<FileInfo>> callback = new RetryingTransactionCallback<List<FileInfo>>()
|
||||||
|
{
|
||||||
|
public List<FileInfo> execute() throws Throwable
|
||||||
|
{
|
||||||
|
return fileFolderService.getNamePath(rootNodeRef, nodeRef);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public FileInfo resolveNamePath(String ticket, final NodeRef rootNodeRef, final List<String> pathElements) throws FileNotFoundException
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<FileInfo> callback = new RetryingTransactionCallback<FileInfo>()
|
||||||
|
{
|
||||||
|
public FileInfo execute() throws Throwable
|
||||||
|
{
|
||||||
|
return fileFolderService.resolveNamePath(rootNodeRef, pathElements);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public FileInfo getFileInfo(String ticket, final NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<FileInfo> callback = new RetryingTransactionCallback<FileInfo>()
|
||||||
|
{
|
||||||
|
public FileInfo execute() throws Throwable
|
||||||
|
{
|
||||||
|
return fileFolderService.getFileInfo(nodeRef);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return retryingTransactionHelper.doInTransaction(callback, true, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public ContentData putContent(
|
||||||
|
String ticket,
|
||||||
|
final NodeRef nodeRef,
|
||||||
|
final byte[] bytes,
|
||||||
|
final String filename)
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<ContentData> callback = new RetryingTransactionCallback<ContentData>()
|
||||||
|
{
|
||||||
|
public ContentData execute() throws Throwable
|
||||||
|
{
|
||||||
|
// Guess the mimetype
|
||||||
|
String mimetype = mimetypeService.guessMimetype(filename);
|
||||||
|
|
||||||
|
// Get a writer
|
||||||
|
ContentWriter writer = fileFolderService.getWriter(nodeRef);
|
||||||
|
// Make a stream
|
||||||
|
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
|
||||||
|
// Guess the encoding
|
||||||
|
ContentCharsetFinder charsetFinder = mimetypeService.getContentCharsetFinder();
|
||||||
|
Charset charset = charsetFinder.getCharset(is, mimetype);
|
||||||
|
// Set metadata
|
||||||
|
writer.setEncoding(charset.name());
|
||||||
|
writer.setMimetype(mimetype);
|
||||||
|
|
||||||
|
// Write the stream
|
||||||
|
writer.putContent(is);
|
||||||
|
|
||||||
|
// Done
|
||||||
|
return writer.getContentData();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ContentData contentData = retryingTransactionHelper.doInTransaction(callback, false, true);
|
||||||
|
// Done
|
||||||
|
return contentData;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public byte[] getContent(String ticket, final NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<byte[]> callback = new RetryingTransactionCallback<byte[]>()
|
||||||
|
{
|
||||||
|
public byte[] execute() throws Throwable
|
||||||
|
{
|
||||||
|
// Get a reader
|
||||||
|
ContentReader reader = fileFolderService.getReader(nodeRef);
|
||||||
|
if (!reader.exists())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the content
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream((int)reader.getSize());
|
||||||
|
reader.getContent(bos);
|
||||||
|
|
||||||
|
// Done
|
||||||
|
return bos.toByteArray();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
byte[] bytes = retryingTransactionHelper.doInTransaction(callback, true, true);
|
||||||
|
// Done
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public ContentReader getReader(String ticket, NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public ContentWriter getWriter(String ticket, NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
239
source/java/org/alfresco/repo/remote/LoaderRemoteServer.java
Normal file
239
source/java/org/alfresco/repo/remote/LoaderRemoteServer.java
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.remote;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.sf.acegisecurity.Authentication;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.node.db.NodeDaoService;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
|
import org.alfresco.service.cmr.remote.LoaderRemote;
|
||||||
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||||
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
|
import org.alfresco.util.PropertyMap;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server side implementation of the <code>LoaderServiceTransport</code> transport
|
||||||
|
* layer. This is the class that gets exported remotely as it contains the
|
||||||
|
* explicit ticket arguments.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
* @since 2.2
|
||||||
|
*/
|
||||||
|
public class LoaderRemoteServer implements LoaderRemote
|
||||||
|
{
|
||||||
|
private static Log logger = LogFactory.getLog(LoaderRemoteServer.class);
|
||||||
|
|
||||||
|
/** The association for the working root node: <b>sys:LoaderServiceWorkingRoot</b> */
|
||||||
|
private static final QName ASSOC_WORKING_ROOT = QName.createQName(
|
||||||
|
NamespaceService.SYSTEM_MODEL_1_0_URI,
|
||||||
|
"LoaderServiceWorkingRoot");
|
||||||
|
|
||||||
|
private RetryingTransactionHelper retryingTransactionHelper;
|
||||||
|
private AuthenticationService authenticationService;
|
||||||
|
private NodeService nodeService;
|
||||||
|
private NodeDaoService nodeDaoService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param transactionService provides transactional support and retrying
|
||||||
|
*/
|
||||||
|
public void setTransactionService(TransactionService transactionService)
|
||||||
|
{
|
||||||
|
this.retryingTransactionHelper = transactionService.getRetryingTransactionHelper();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param authenticationService the service that will validate the tickets
|
||||||
|
*/
|
||||||
|
public void setAuthenticationService(AuthenticationService authenticationService)
|
||||||
|
{
|
||||||
|
this.authenticationService = authenticationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param nodeService the service that will do the work
|
||||||
|
*/
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param nodeDaoService the DAO for node queries
|
||||||
|
*/
|
||||||
|
public void setNodeDaoService(NodeDaoService nodeDaoService)
|
||||||
|
{
|
||||||
|
this.nodeDaoService = nodeDaoService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public String authenticate(String username, String password)
|
||||||
|
{
|
||||||
|
// We need to authenticate
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.authenticate(username, password.toCharArray());
|
||||||
|
String ticket = authenticationService.getCurrentTicket();
|
||||||
|
// Done
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Authenticated: " + username);
|
||||||
|
}
|
||||||
|
return ticket;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public NodeRef getOrCreateWorkingRoot(String ticket, final StoreRef storeRef)
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<NodeRef> callback = new RetryingTransactionCallback<NodeRef>()
|
||||||
|
{
|
||||||
|
public NodeRef execute() throws Throwable
|
||||||
|
{
|
||||||
|
NodeRef rootNodeRef = null;
|
||||||
|
// Check if the store exists
|
||||||
|
if (!nodeService.exists(storeRef))
|
||||||
|
{
|
||||||
|
nodeService.createStore(storeRef.getProtocol(), storeRef.getIdentifier());
|
||||||
|
}
|
||||||
|
rootNodeRef = nodeService.getRootNode(storeRef);
|
||||||
|
// Look for the working root
|
||||||
|
List<ChildAssociationRef> assocRefs = nodeService.getChildAssocs(
|
||||||
|
rootNodeRef,
|
||||||
|
ContentModel.ASSOC_CHILDREN,
|
||||||
|
ASSOC_WORKING_ROOT);
|
||||||
|
NodeRef workingRootNodeRef = null;
|
||||||
|
if (assocRefs.size() > 0)
|
||||||
|
{
|
||||||
|
// Just use the first one
|
||||||
|
workingRootNodeRef = assocRefs.get(0).getChildRef();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
String username = authenticationService.getCurrentUserName();
|
||||||
|
// We have to make it. Touch the root node to act as an optimistic lock.
|
||||||
|
nodeService.setProperty(rootNodeRef, ContentModel.PROP_AUTHOR, username);
|
||||||
|
// Add a cm:folder below the root
|
||||||
|
PropertyMap properties = new PropertyMap();
|
||||||
|
properties.put(ContentModel.PROP_NAME, "Loader Application Root");
|
||||||
|
workingRootNodeRef = nodeService.createNode(
|
||||||
|
rootNodeRef,
|
||||||
|
ContentModel.ASSOC_CHILDREN,
|
||||||
|
ASSOC_WORKING_ROOT,
|
||||||
|
ContentModel.TYPE_FOLDER,
|
||||||
|
properties).getChildRef();
|
||||||
|
}
|
||||||
|
// Done
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Got working root node: " + workingRootNodeRef);
|
||||||
|
}
|
||||||
|
return workingRootNodeRef;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return retryingTransactionHelper.doInTransaction(callback, false, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public int getNodeCount(String ticket)
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<Integer> callback = new RetryingTransactionCallback<Integer>()
|
||||||
|
{
|
||||||
|
public Integer execute() throws Throwable
|
||||||
|
{
|
||||||
|
return nodeDaoService.getNodeCount();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return retryingTransactionHelper.doInTransaction(callback, false, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public int getNodeCount(String ticket, final StoreRef storeRef)
|
||||||
|
{
|
||||||
|
Authentication authentication = AuthenticationUtil.getCurrentAuthentication();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authenticationService.validate(ticket);
|
||||||
|
// Make the call
|
||||||
|
RetryingTransactionCallback<Integer> callback = new RetryingTransactionCallback<Integer>()
|
||||||
|
{
|
||||||
|
public Integer execute() throws Throwable
|
||||||
|
{
|
||||||
|
return nodeDaoService.getNodeCount(storeRef);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return retryingTransactionHelper.doInTransaction(callback, false, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setCurrentAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.service.cmr.remote;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.model.FileExistsException;
|
||||||
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
|
import org.alfresco.service.cmr.model.FileInfo;
|
||||||
|
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentData;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remote transport interface for the <code>FileFolderService</code>. This includes the
|
||||||
|
* authentication tickets and abstracts the stream transport as well.
|
||||||
|
* <p/>
|
||||||
|
* <b>NOTE:</b> This is not a production API and will most definitely be changed or removed.
|
||||||
|
*
|
||||||
|
* @see org.alfresco.service.cmr.model.FileFolderService
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
* @since 2.2.
|
||||||
|
*/
|
||||||
|
public interface FileFolderRemote
|
||||||
|
{
|
||||||
|
/** The service name <b>org.alfresco.FileFolderRemote</b> */
|
||||||
|
public static final String SERVICE_NAME = "org.alfresco.FileFolderRemote";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param token the authentication ticket
|
||||||
|
*
|
||||||
|
* @see FileFolderService#list(NodeRef)
|
||||||
|
*/
|
||||||
|
public List<FileInfo> list(String ticket, NodeRef contextNodeRef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param token the authentication ticket
|
||||||
|
*
|
||||||
|
* @see FileFolderService#listFiles(NodeRef)
|
||||||
|
*/
|
||||||
|
public List<FileInfo> listFiles(String ticket, NodeRef folderNodeRef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param token the authentication ticket
|
||||||
|
*
|
||||||
|
* @see FileFolderService#listFolders(NodeRef)
|
||||||
|
*/
|
||||||
|
public List<FileInfo> listFolders(String ticket, NodeRef contextNodeRef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param token the authentication ticket
|
||||||
|
*
|
||||||
|
* @see FileFolderService#searchSimple(NodeRef, String)
|
||||||
|
*/
|
||||||
|
public NodeRef searchSimple(String ticket, NodeRef contextNodeRef, String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param token the authentication ticket
|
||||||
|
*
|
||||||
|
* @see FileFolderService#search(NodeRef, String, boolean)
|
||||||
|
*/
|
||||||
|
public List<FileInfo> search(
|
||||||
|
String ticket,
|
||||||
|
NodeRef contextNodeRef,
|
||||||
|
String namePattern,
|
||||||
|
boolean includeSubFolders);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param token the authentication ticket
|
||||||
|
*
|
||||||
|
* @see FileFolderService#search(NodeRef, String, boolean, boolean, boolean)
|
||||||
|
*/
|
||||||
|
public List<FileInfo> search(
|
||||||
|
String ticket,
|
||||||
|
NodeRef contextNodeRef,
|
||||||
|
String namePattern,
|
||||||
|
boolean fileSearch,
|
||||||
|
boolean folderSearch,
|
||||||
|
boolean includeSubFolders);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param token the authentication ticket
|
||||||
|
*
|
||||||
|
* @see FileFolderService#rename(NodeRef, String)
|
||||||
|
*/
|
||||||
|
public FileInfo rename(String ticket, NodeRef fileFolderRef, String newName) throws FileExistsException, FileNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param token the authentication ticket
|
||||||
|
*
|
||||||
|
* @see FileFolderService#move(NodeRef, NodeRef, String)
|
||||||
|
*/
|
||||||
|
public FileInfo move(String ticket, NodeRef sourceNodeRef, NodeRef targetParentRef, String newName)
|
||||||
|
throws FileExistsException, FileNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param token the authentication ticket
|
||||||
|
*
|
||||||
|
* @see FileFolderService#copy(NodeRef, NodeRef, String)
|
||||||
|
*/
|
||||||
|
public FileInfo copy(String ticket, NodeRef sourceNodeRef, NodeRef targetParentRef, String newName)
|
||||||
|
throws FileExistsException, FileNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param token the authentication ticket
|
||||||
|
*
|
||||||
|
* @see FileFolderService#create(NodeRef, String, QName)
|
||||||
|
*/
|
||||||
|
public FileInfo create(String ticket, NodeRef parentNodeRef, String name, QName typeQName) throws FileExistsException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param token the authentication ticket
|
||||||
|
*
|
||||||
|
* @see FileFolderService#delete(NodeRef)
|
||||||
|
*/
|
||||||
|
public void delete(String ticket, NodeRef nodeRef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param token the authentication ticket
|
||||||
|
*
|
||||||
|
* @see FileFolderService#makeFolders(NodeRef, List, QName)
|
||||||
|
*/
|
||||||
|
public FileInfo makeFolders(String ticket, NodeRef parentNodeRef, List<String> pathElements, QName folderTypeQName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param token the authentication ticket
|
||||||
|
*
|
||||||
|
* @see FileFolderService#getNamePath(NodeRef, NodeRef)
|
||||||
|
*/
|
||||||
|
public List<FileInfo> getNamePath(String ticket, NodeRef rootNodeRef, NodeRef nodeRef) throws FileNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param token the authentication ticket
|
||||||
|
*
|
||||||
|
* @see FileFolderService#resolveNamePath(NodeRef, List)
|
||||||
|
*/
|
||||||
|
public FileInfo resolveNamePath(String ticket, NodeRef rootNodeRef, List<String> pathElements) throws FileNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param token the authentication ticket
|
||||||
|
*
|
||||||
|
* @see FileFolderService#getFileInfo(NodeRef)
|
||||||
|
*/
|
||||||
|
public FileInfo getFileInfo(String ticket, NodeRef nodeRef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Refactor!!!
|
||||||
|
* The dirtiest of hacks. When time permits, the APIs and implementations will be properly refactored.
|
||||||
|
* For now, this remains adequate for small files.
|
||||||
|
*/
|
||||||
|
public ContentData putContent(String ticket, NodeRef nodeRef, byte[] bytes, String filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Refactor!!!
|
||||||
|
*/
|
||||||
|
public byte[] getContent(String ticket, NodeRef nodeRef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param token the authentication ticket
|
||||||
|
*
|
||||||
|
* @see FileFolderService#getReader(NodeRef)
|
||||||
|
*/
|
||||||
|
public ContentReader getReader(String ticket, NodeRef nodeRef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param token the authentication ticket
|
||||||
|
*
|
||||||
|
* @see FileFolderService#getWriter(NodeRef)
|
||||||
|
*/
|
||||||
|
public ContentWriter getWriter(String ticket, NodeRef nodeRef);
|
||||||
|
}
|
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.service.cmr.remote;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remote transport interface for the Loader application. This adds functionality
|
||||||
|
* that is generally required by the application and that is not available on other
|
||||||
|
* interfaces.
|
||||||
|
*
|
||||||
|
* @see FileFolderRemote
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
* @since 2.2.
|
||||||
|
*/
|
||||||
|
public interface LoaderRemote
|
||||||
|
{
|
||||||
|
/** The service name <b>org.alfresco.LoaderRemote</b> */
|
||||||
|
public static final String SERVICE_NAME = "org.alfresco.LoaderRemote";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authenticate on the server using the given username and password
|
||||||
|
*
|
||||||
|
* @return the authentication ticket
|
||||||
|
*/
|
||||||
|
public String authenticate(String username, String password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the working <b>cm:folder</b> node for the given store. If there is no working
|
||||||
|
* root node, then one is created.
|
||||||
|
*
|
||||||
|
* @param ticket the authentication ticket
|
||||||
|
* @param storeRef the store reference
|
||||||
|
* @return a working <b>cm:folder</b> to use as the root for loading,
|
||||||
|
* or <tt>null</tt> if it is not available.
|
||||||
|
*/
|
||||||
|
public NodeRef getOrCreateWorkingRoot(String ticket, StoreRef storeRef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ticket the authentication ticket
|
||||||
|
* @return Returns the total number of ADM nodes
|
||||||
|
*/
|
||||||
|
public int getNodeCount(String ticket);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ticket the authentication ticket
|
||||||
|
* @param storeRef the store to query against
|
||||||
|
* @return Returns the total number of nodes for the given ADM store
|
||||||
|
*/
|
||||||
|
public int getNodeCount(String ticket, StoreRef storeRef);
|
||||||
|
}
|
Reference in New Issue
Block a user