Moving to root below branch label

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2005 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2005-12-08 07:13:07 +00:00
commit 3e7141dc1a
225 changed files with 48004 additions and 0 deletions

View File

@@ -0,0 +1,263 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.example.webservice;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Properties;
import javax.xml.rpc.ServiceException;
import junit.framework.AssertionFailedError;
import org.alfresco.example.webservice.authentication.AuthenticationResult;
import org.alfresco.example.webservice.authentication.AuthenticationServiceLocator;
import org.alfresco.example.webservice.authentication.AuthenticationServiceSoapBindingStub;
import org.alfresco.example.webservice.content.Content;
import org.alfresco.example.webservice.content.ContentServiceLocator;
import org.alfresco.example.webservice.content.ContentServiceSoapBindingStub;
import org.alfresco.example.webservice.repository.RepositoryServiceLocator;
import org.alfresco.example.webservice.repository.RepositoryServiceSoapBindingStub;
import org.alfresco.example.webservice.repository.UpdateResult;
import org.alfresco.example.webservice.types.CML;
import org.alfresco.example.webservice.types.CMLCreate;
import org.alfresco.example.webservice.types.ContentFormat;
import org.alfresco.example.webservice.types.NamedValue;
import org.alfresco.example.webservice.types.ParentReference;
import org.alfresco.example.webservice.types.Predicate;
import org.alfresco.example.webservice.types.Reference;
import org.alfresco.example.webservice.types.Store;
import org.alfresco.example.webservice.types.StoreEnum;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.BaseTest;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.configuration.FileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Base class for all web service system tests that need to authenticate. The
* setUp method calls the AuthenticationService and authenticates as
* admin/admin, the returned ticket is then stored in
* <code>TicketHolder.ticket</code> so that all subclass implementations can
* use it to call other services.
*
* @see junit.framework.TestCase#setUp()
* @author gavinc
*/
public abstract class BaseWebServiceSystemTest extends BaseTest
{
private static Log logger = LogFactory
.getLog(BaseWebServiceSystemTest.class);
protected static final String USERNAME = "admin";
protected static final String PASSWORD = "admin";
private Properties properties;
private Store store;
private Reference rootNodeReference;
private Reference contentReference;
protected RepositoryServiceSoapBindingStub repositoryService;
protected ContentServiceSoapBindingStub contentService;
public BaseWebServiceSystemTest()
{
try
{
EngineConfiguration config = new FileProvider(getResourcesDir(), "client-deploy.wsdd");
this.contentService = (ContentServiceSoapBindingStub)new ContentServiceLocator(config).getContentService();
assertNotNull(this.contentService);
this.contentService.setTimeout(60000);
this.repositoryService = (RepositoryServiceSoapBindingStub)new RepositoryServiceLocator(config).getRepositoryService();
assertNotNull(this.repositoryService);
this.repositoryService.setTimeout(60000);
}
catch (Exception e)
{
fail("Could not instantiate the content service" + e.toString());
}
}
/**
* Calls the AuthenticationService to retrieve a ticket for all tests to
* use.
*/
@Override
protected void setUp() throws Exception
{
super.setUp();
AuthenticationServiceSoapBindingStub authSvc = null;
try
{
authSvc = (AuthenticationServiceSoapBindingStub) new AuthenticationServiceLocator()
.getAuthenticationService();
} catch (ServiceException jre)
{
if (jre.getLinkedCause() != null)
{
jre.getLinkedCause().printStackTrace();
}
throw new AssertionFailedError("JAX-RPC ServiceException caught: "
+ jre);
}
assertNotNull("authSvc is null", authSvc);
// Time out after a minute
authSvc.setTimeout(60000);
// call the authenticate method and retrieve the ticket
AuthenticationResult result = authSvc.startSession(USERNAME, PASSWORD);
assertNotNull("result is null", result);
String ticket = result.getTicket();
assertNotNull("ticket is null", ticket);
TicketHolder.ticket = ticket;
if (logger.isDebugEnabled())
{
logger.debug("Retrieved and stored ticket: " + TicketHolder.ticket);
}
}
protected Store getStore()
{
if (this.store == null)
{
String strStoreRef = getProperties().getProperty(
WebServiceBootstrapSystemTest.PROP_STORE_REF);
StoreRef storeRef = new StoreRef(strStoreRef);
this.store = new Store(StoreEnum.fromValue(storeRef.getProtocol()),
storeRef.getIdentifier());
}
return this.store;
}
protected Reference getRootNodeReference()
{
if (this.rootNodeReference == null)
{
String strNodeRef = getProperties().getProperty(
WebServiceBootstrapSystemTest.PROP_ROOT_NODE_REF);
NodeRef rootNodeRef = new NodeRef(strNodeRef);
this.rootNodeReference = new Reference(getStore(), rootNodeRef
.getId(), null);
}
return this.rootNodeReference;
}
protected Reference getContentReference()
{
if (this.contentReference == null)
{
String strNodeRef = getProperties().getProperty(WebServiceBootstrapSystemTest.PROP_CONTENT_NODE_REF);
NodeRef nodeRef = new NodeRef(strNodeRef);
this.contentReference = new Reference(getStore(), nodeRef.getId(), null);
}
return this.contentReference;
}
protected ParentReference getFolderParentReference(QName assocName)
{
NodeRef folderNodeRef = getFolderNodeRef();
ParentReference parentReference = new ParentReference();
parentReference.setStore(getStore());
parentReference.setUuid(folderNodeRef.getId());
parentReference.setAssociationType(ContentModel.ASSOC_CONTAINS.toString());
parentReference.setChildName(assocName.toString());
return parentReference;
}
protected Reference createContentAtRoot(String name, String contentValue) throws Exception
{
ParentReference parentRef = new ParentReference();
parentRef.setStore(getStore());
parentRef.setUuid(getRootNodeReference().getUuid());
parentRef.setAssociationType(ContentModel.ASSOC_CHILDREN.toString());
parentRef.setChildName(ContentModel.ASSOC_CHILDREN.toString());
NamedValue[] properties = new NamedValue[]{new NamedValue(ContentModel.PROP_NAME.toString(), name)};
CMLCreate create = new CMLCreate("1", parentRef, ContentModel.TYPE_CONTENT.toString(), properties);
CML cml = new CML();
cml.setCreate(new CMLCreate[]{create});
UpdateResult[] result = this.repositoryService.update(cml);
Reference newContentNode = result[0].getDestination();
Content content = this.contentService.write(newContentNode, ContentModel.PROP_CONTENT.toString(), contentValue.getBytes(), new ContentFormat("text/plain", "UTF-8"));
assertNotNull(content);
assertNotNull(content.getFormat());
assertEquals("text/plain", content.getFormat().getMimetype());
return content.getNode();
}
/**
* Get the content from the download servlet
*
* @param url
* @return
*/
protected String getContentAsString(String strUrl) throws Exception
{
// Add the ticket to the url
strUrl += "?ticket=" + TicketHolder.ticket;
StringBuilder readContent = new StringBuilder();
URL url = new URL(strUrl);
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
int read = is.read();
while (read != -1)
{
readContent.append((char)read);
read = is.read();
}
return readContent.toString();
}
protected Predicate convertToPredicate(Reference reference)
{
Predicate predicate = new Predicate();
predicate.setNodes(new Reference[] {reference});
return predicate;
}
private Properties getProperties()
{
if (this.properties == null)
{
this.properties = WebServiceBootstrapSystemTest
.getBootstrapProperties();
}
return this.properties;
}
private NodeRef getFolderNodeRef()
{
String strNodeRef = getProperties().getProperty(WebServiceBootstrapSystemTest.PROP_FOLDER_NODE_REF);
return new NodeRef(strNodeRef);
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.example.webservice;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
/**
* Implements CallbackHandler which returns the currently stored ticket in
* the static <code>ticket</code> field.
*
* @author gavinc
*/
public class TicketHolder implements CallbackHandler
{
public static String ticket;
/**
* @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
*/
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
{
for (int i = 0; i < callbacks.length; i++)
{
if (callbacks[i] instanceof WSPasswordCallback)
{
WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
pc.setPassword(ticket);
}
else
{
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
}
}
}
}

View File

@@ -0,0 +1,193 @@
package org.alfresco.example.webservice;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.transaction.UserTransaction;
import junit.framework.TestCase;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
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.view.ImporterService;
import org.alfresco.service.cmr.view.Location;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.sun.corba.se.impl.orb.ParserTable.TestContactInfoListFactory;
public class WebServiceBootstrapSystemTest extends TestCase
{
/**
* NOTE: You need to set the location of the indexes and content store to be a non-realtive
* location in the repository.properties file otherwise running this test here will not
* populate the correct index and content store and the test won't work when running against
* the repository
*/
public static final String FOLDER_NAME = "test folder";
public static final String CONTENT_NAME = "test content";
public static final String PROP_STORE_REF = "storeRef";
public static final String PROP_ROOT_NODE_REF = "rootNodeRef";
public static final String PROP_FOLDER_NODE_REF = "folderNodeRef";
public static final String PROP_CONTENT_NODE_REF = "contentNodeRef";
private static final String TEMP_BOOTSTRAP_PROPERTIES = "./WebServiceTestBootstrap.properties";
private static final String TEST_CONTENT = "This is some test content. This is some test content.";
/**
* Runs the bootstrap and populates the property file with the infomration required for the tests
*/
public void testBootstrap()
{
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:alfresco/application-context.xml");
// Get the services
TransactionService transactionService = (TransactionService)applicationContext.getBean("transactionComponent");
AuthenticationComponent authenticationComponent = (AuthenticationComponent)applicationContext.getBean("authenticationComponent");
NodeService nodeService = (NodeService)applicationContext.getBean("NodeService");
ContentService contentService = (ContentService)applicationContext.getBean("contentService");
ImporterService importerService = (ImporterService)applicationContext.getBean("importerComponent");
UserTransaction userTransaction = transactionService.getUserTransaction();
authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName());
try
{
StoreRef storeRef = null;
NodeRef rootNodeRef = null;
NodeRef folderNodeRef = null;
NodeRef testContent = null;
try
{
userTransaction.begin();
// Create the store
storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
rootNodeRef = rootNodeRef = nodeService.getRootNode(storeRef);
// Import the categories
InputStream viewStream = getClass().getClassLoader().getResourceAsStream("alfresco/bootstrap/categories.xml");
BufferedReader reader = new BufferedReader(new InputStreamReader(viewStream));
Location importLocation = new Location(storeRef);
importLocation.setPath("/");
importerService.importView(reader, importLocation, null, null);
// Folder properties
Map<QName, Serializable> folderProps = new HashMap<QName, Serializable>(1);
folderProps.put(ContentModel.PROP_NAME, FOLDER_NAME);
// Create a folder
folderNodeRef = nodeService.createNode(
rootNodeRef,
ContentModel.ASSOC_CHILDREN,
ContentModel.ASSOC_CHILDREN,
ContentModel.TYPE_FOLDER,
folderProps).getChildRef();
Map<QName, Serializable> contentProps = new HashMap<QName, Serializable>(3);
contentProps.put(ContentModel.PROP_NAME, CONTENT_NAME);
// Create some test content
testContent = nodeService.createNode(
rootNodeRef,
ContentModel.ASSOC_CHILDREN,
ContentModel.ASSOC_CHILDREN,
ContentModel.TYPE_CONTENT,
contentProps).getChildRef();
ContentWriter writer = contentService.getWriter(testContent, ContentModel.PROP_CONTENT, true);
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.setEncoding("UTF-8");
writer.putContent(TEST_CONTENT);
// Add the translatable aspect to the test content
nodeService.addAspect(testContent, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "translatable"), null);
// Create content to be the translation of the translatable content
NodeRef testContent2 = nodeService.createNode(
rootNodeRef,
ContentModel.ASSOC_CHILDREN,
ContentModel.ASSOC_CHILDREN,
ContentModel.TYPE_CONTENT,
contentProps).getChildRef();
ContentWriter writer2 = contentService.getWriter(testContent2, ContentModel.PROP_CONTENT, true);
writer2.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer2.setEncoding("UTF-8");
writer2.putContent(TEST_CONTENT);
// Add the association from the master content to the translated content
nodeService.createAssociation(testContent, testContent2, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "translations"));
userTransaction.commit();
}
catch(Throwable e)
{
// rollback the transaction
try { if (userTransaction != null) {userTransaction.rollback();} } catch (Exception ex) {}
try {authenticationComponent.clearCurrentSecurityContext(); } catch (Exception ex) {}
throw new AlfrescoRuntimeException("Bootstrap failed", e);
}
Properties properties = new Properties();
properties.put(PROP_STORE_REF, storeRef.toString());
properties.put(PROP_ROOT_NODE_REF, rootNodeRef.toString());
properties.put(PROP_FOLDER_NODE_REF, folderNodeRef.toString());
properties.put(PROP_CONTENT_NODE_REF, testContent.toString());
try
{
OutputStream outputStream = new FileOutputStream(TEMP_BOOTSTRAP_PROPERTIES);
properties.store(outputStream, "Web service node store details");
outputStream.flush();
}
catch (Exception e)
{
e.printStackTrace();
fail("Unable to store bootstrap details.");
}
//System.out.println(NodeStoreInspector.dumpNodeStore(nodeService, storeRef));
}
finally
{
authenticationComponent.clearCurrentSecurityContext();
}
}
public static Properties getBootstrapProperties()
{
Properties properties = new Properties();
try
{
InputStream inputStream = new FileInputStream(TEMP_BOOTSTRAP_PROPERTIES);
properties.load(inputStream);
}
catch (Exception e)
{
e.printStackTrace();
fail("Unable to load test bootstrap details. Try running WebServiceBootstrapSystem test, then re-start container and try again.");
}
return properties;
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.example.webservice;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.alfresco.example.webservice.authentication.AuthenticationServiceSystemTest;
import org.alfresco.example.webservice.authoring.AuthoringServiceSystemTest;
import org.alfresco.example.webservice.classification.ClassificationServiceSystemTest;
import org.alfresco.example.webservice.content.ContentServiceSystemTest;
import org.alfresco.example.webservice.repository.RepositoryServiceSystemTest;
import org.alfresco.repo.webservice.CMLUtilTest;
public class WebServiceSuiteSystemTest extends TestSuite
{
public static Test suite()
{
TestSuite suite = new TestSuite();
suite.addTestSuite(CMLUtilTest.class);
suite.addTestSuite(AuthenticationServiceSystemTest.class);
suite.addTestSuite(AuthoringServiceSystemTest.class);
suite.addTestSuite(ClassificationServiceSystemTest.class);
suite.addTestSuite(ContentServiceSystemTest.class);
suite.addTestSuite(RepositoryServiceSystemTest.class);
return suite;
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.example.webservice.authentication;
import javax.xml.rpc.ServiceException;
import junit.framework.AssertionFailedError;
import org.alfresco.util.BaseTest;
/**
* Tests the AuthenticationService by trying to login as admin/admin and
* attempting to login with incorrect credentials.
*
* @author gavinc
*/
public class AuthenticationServiceSystemTest extends BaseTest
{
private AuthenticationServiceSoapBindingStub binding;
/**
* @see junit.framework.TestCase#setUp()
*/
@Override
protected void setUp() throws Exception
{
super.setUp();
try
{
this.binding = (AuthenticationServiceSoapBindingStub)new AuthenticationServiceLocator().getAuthenticationService();
}
catch (ServiceException jre)
{
if (jre.getLinkedCause() != null)
{
jre.getLinkedCause().printStackTrace();
}
throw new AssertionFailedError("JAX-RPC ServiceException caught: " + jre);
}
assertNotNull("binding is null", this.binding);
// Time out after a minute
binding.setTimeout(60000);
}
/**
* Tests whether the authentication service is working correctly
*
* @throws Exception
*/
public void testSuccessfulLogin() throws Exception
{
try
{
AuthenticationResult value = this.binding.startSession("admin", "admin");
assertNotNull("result must not be null", value);
System.out.println("ticket = " + value.getTicket());
}
catch (AuthenticationFault error)
{
throw new AssertionFailedError("AuthenticationFault Exception caught: " + error);
}
}
/**
* Tests that a failed authentication attempt fails as expected
*
* @throws Exception
*/
public void testFailedLogin() throws Exception
{
try
{
AuthenticationResult result = this.binding.startSession("wrong", "credentials");
fail("The credentials are incorrect so an AuthenticationFault should have been thrown");
}
catch (AuthenticationFault error)
{
// we expected this
}
}
public void testEndSession() throws Exception
{
this.binding.startSession("admin", "admin");
this.binding.endSession();
}
}

View File

@@ -0,0 +1,371 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.example.webservice.authoring;
import javax.xml.rpc.ServiceException;
import junit.framework.AssertionFailedError;
import org.alfresco.example.webservice.BaseWebServiceSystemTest;
import org.alfresco.example.webservice.content.Content;
import org.alfresco.example.webservice.types.ContentFormat;
import org.alfresco.example.webservice.types.NamedValue;
import org.alfresco.example.webservice.types.ParentReference;
import org.alfresco.example.webservice.types.Predicate;
import org.alfresco.example.webservice.types.Reference;
import org.alfresco.example.webservice.types.Version;
import org.alfresco.example.webservice.types.VersionHistory;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.namespace.QName;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.configuration.FileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class AuthoringServiceSystemTest extends BaseWebServiceSystemTest
{
@SuppressWarnings("unused")
private static Log logger = LogFactory.getLog(AuthoringServiceSystemTest.class);
private static final String INITIAL_VERSION_CONTENT = "Content of the initial version";
private static final String SECOND_VERSION_CONTENT = "The content for the second version is completely different";
private static final String VALUE_DESCRIPTION = "description";
private AuthoringServiceSoapBindingStub authoringService;
@Override
protected void setUp() throws Exception
{
super.setUp();
try
{
EngineConfiguration config = new FileProvider(getResourcesDir(),
"client-deploy.wsdd");
this.authoringService = (AuthoringServiceSoapBindingStub) new AuthoringServiceLocator(
config).getAuthoringService();
}
catch (ServiceException jre)
{
if (jre.getLinkedCause() != null)
{
jre.getLinkedCause().printStackTrace();
}
throw new AssertionFailedError("JAX-RPC ServiceException caught: "
+ jre);
}
assertNotNull(this.authoringService);
// Time out after a minute
this.authoringService.setTimeout(60000);
}
/**
* Tests the checkout service method
*
* @throws Exception
*/
public void testCheckout() throws Exception
{
doCheckOut();
// TODO test multiple checkout
}
/**
* Reusable method to do a standard checkout
*
* @return
* @throws Exception
*/
private Reference doCheckOut() throws Exception
{
// Use the helper to create the verionable node
Reference reference = createContentAtRoot("version_test.txt", INITIAL_VERSION_CONTENT);
Predicate predicate = convertToPredicate(reference);
// Check the content out (to the same detination)
CheckoutResult result = this.authoringService.checkout(predicate, null);
assertNotNull(result);
assertEquals(1, result.getOriginals().length);
assertEquals(1, result.getWorkingCopies().length);
// TODO need to check that the working copy and the origional are in the correct states ...
return result.getWorkingCopies()[0];
}
/**
* Tests the checkout service method passing a destination for the working
* copy
*
* @throws Exception
*/
public void testCheckoutWithDestination() throws Exception
{
Reference reference = createContentAtRoot("version_test.txt", INITIAL_VERSION_CONTENT);
Predicate predicate = convertToPredicate(reference);
ParentReference parentReference = getFolderParentReference(QName.createQName("{test}workingCopy"));
// Checkout the content to the folder
CheckoutResult result = this.authoringService.checkout(predicate, parentReference);
assertNotNull(result);
assertEquals(1, result.getOriginals().length);
assertEquals(1, result.getWorkingCopies().length);
// TODO need to check that the working copy and the origional are in the correct states
}
/**
* Tests the checkin service method
*
* @throws Exception
*/
public void testCheckin() throws Exception
{
// First we need to check a document out
Reference workingCopy = doCheckOut();
// Check in but keep checked out
Predicate predicate = convertToPredicate(workingCopy);
NamedValue[] comments = getVersionComments();
CheckinResult checkinResult = this.authoringService.checkin(predicate, comments, true);
// Check the result
assertNotNull(checkinResult);
assertEquals(1, checkinResult.getCheckedIn().length);
assertEquals(1, checkinResult.getWorkingCopies().length);
// TODO check that state of the orig and working copies
// Checkin but don't keep checked out
Predicate predicate2 = convertToPredicate(checkinResult.getWorkingCopies()[0]);
CheckinResult checkinResult2 = this.authoringService.checkin(predicate2, comments, false);
// Check the result
assertNotNull(checkinResult2);
assertEquals(1, checkinResult2.getCheckedIn().length);
assertNull(checkinResult2.getWorkingCopies());
// TODO check the above behaviour ...
// TODO check that the state of the org and working copies
// TODO check multiple checkin
}
/**
* Helper method to get a list of version comments
*
* @return
*/
private NamedValue[] getVersionComments()
{
NamedValue[] comments = new NamedValue[1];
comments[0] = new NamedValue(org.alfresco.service.cmr.version.Version.PROP_DESCRIPTION, VALUE_DESCRIPTION);
return comments;
}
/**
* Tests the checkinExternal service method
*
* @throws Exception
*/
public void testCheckinExternal() throws Exception
{
// First we need to check a document out
Reference workingCopy = doCheckOut();
// Check in with external content
NamedValue[] comments = getVersionComments();
ContentFormat contentFormat = new ContentFormat(MimetypeMap.MIMETYPE_TEXT_PLAIN, "UTF-8");
Reference origionalNode = this.authoringService.checkinExternal(workingCopy, comments, false, contentFormat, SECOND_VERSION_CONTENT.getBytes());
// Check the origianl Node
assertNotNull(origionalNode);
Content[] contents = this.contentService.read(new Predicate(new Reference[]{origionalNode}, getStore(), null), ContentModel.PROP_CONTENT.toString());
Content readResult = contents[0];
assertNotNull(readResult);
String checkedInContent = getContentAsString(readResult.getUrl());
assertNotNull(checkedInContent);
assertEquals(SECOND_VERSION_CONTENT, checkedInContent);
}
/**
* Tests the cancelCheckout service method
*
* @throws Exception
*/
public void testCancelCheckout() throws Exception
{
// Check out a node
Reference workingCopy = doCheckOut();
// Cancel the check out
Predicate predicate = convertToPredicate(workingCopy);
CancelCheckoutResult result = this.authoringService.cancelCheckout(predicate);
// Check the result
assertNotNull(result);
assertEquals(1, result.getOriginals().length);
// TODO check that state of the orig and that the working copy has been deleted
// TODO I don't think that the working copies should be returned in the result since they have been deleted !!
}
/**
* Tests the lock service methods, lock, unlock and getStaus
*
* @throws Exception
*/
public void testLockUnLockGetStatus() throws Exception
{
Reference reference = createContentAtRoot("lock_test1.txt", INITIAL_VERSION_CONTENT);
Predicate predicate = convertToPredicate(reference);
// Get the status
checkLockStatus(predicate, null, null);
// Lock with a write lock
Reference[] lockedRefs = this.authoringService.lock(predicate, false, LockTypeEnum.write);
assertNotNull(lockedRefs);
assertEquals(1, lockedRefs.length);
// TODO check in more detail
// Get the status
checkLockStatus(predicate, USERNAME, LockTypeEnum.write);
// Unlock (bad)
// try
// {
// this.authoringService.unlock(predicate, "bad", false);
// fail("This should have thrown an exception.");
// }
// catch (Throwable exception)
// {
// // Good .. we where expceting this
// }
// Unlock (good)
Reference[] unlocked = this.authoringService.unlock(predicate, false);
assertNotNull(unlocked);
assertEquals(1, unlocked.length);
// Get the status
checkLockStatus(predicate, null, null);
// Read lock
Reference[] lockedRefs2 = this.authoringService.lock(predicate, false, LockTypeEnum.read);
assertNotNull(lockedRefs2);
assertEquals(1, lockedRefs2.length);
// TODO check in more detail
// Get the status
checkLockStatus(predicate, USERNAME, LockTypeEnum.read);
}
private void checkLockStatus(Predicate predicate, String lockOwner, LockTypeEnum lockType)
throws Exception
{
LockStatus[] lockStatus1 = this.authoringService.getLockStatus(predicate);
assertNotNull(lockStatus1);
assertEquals(1, lockStatus1.length);
LockStatus ls1 = lockStatus1[0];
assertNotNull(ls1);
assertEquals(lockOwner, ls1.getLockOwner());
assertEquals(lockType, ls1.getLockType());
}
/**
* Tests the createVersion service method
*
* @throws Exception
*/
public void testVersionMethods() throws Exception
{
Reference reference = createContentAtRoot("create_version_test.txt", INITIAL_VERSION_CONTENT);
Predicate predicate = convertToPredicate(reference);
// Get the version history (before its been versioned)
VersionHistory emptyVersionHistory = this.authoringService.getVersionHistory(reference);
assertNotNull(emptyVersionHistory);
assertNull(emptyVersionHistory.getVersions());
// Create the version
VersionResult result = this.authoringService.createVersion(predicate, getVersionComments(), false);
assertNotNull(result);
assertEquals(1, result.getNodes().length);
assertEquals(1, result.getVersions().length);
Version version = result.getVersions()[0];
assertEquals("1.0", version.getLabel());
// TODO check commentaries
// TODO check creator
// Get the version history
VersionHistory versionHistory = this.authoringService.getVersionHistory(reference);
assertNotNull(versionHistory);
assertEquals(2, versionHistory.getVersions().length);
// TODO some more tests ...
// Update the content
this.contentService.write(reference, ContentModel.PROP_CONTENT.toString(), SECOND_VERSION_CONTENT.getBytes(), null);
// Create another version
VersionResult versionResult2 = this.authoringService.createVersion(predicate, getVersionComments(), false);
assertNotNull(versionResult2);
assertEquals(1, versionResult2.getNodes().length);
assertEquals(1, versionResult2.getVersions().length);
Version version2 = versionResult2.getVersions()[0];
assertEquals("1.3", version2.getLabel());
// TODO check commentaries
// TODO check creator
// Check the version history
VersionHistory versionHistory2 = this.authoringService.getVersionHistory(reference);
assertNotNull(versionHistory2);
assertEquals(4, versionHistory2.getVersions().length);
// TODO some more tests ...
// Confirm the current content of the node
Content[] contents = this.contentService.read(new Predicate(new Reference[]{reference}, getStore(), null), ContentModel.PROP_CONTENT.toString());
Content readResult1 = contents[0];
String content1 = getContentAsString(readResult1.getUrl());
assertEquals(SECOND_VERSION_CONTENT, content1);
// Revert the node to the first version
this.authoringService.revertVersion(reference, "1.0");
// Confirm that the state of the node has been reverted
Content[] contents2 = this.contentService.read(new Predicate(new Reference[]{reference}, getStore(), null), ContentModel.PROP_CONTENT.toString());
Content readResult2 = contents2[0];
String content2 = getContentAsString(readResult2.getUrl());
assertEquals(INITIAL_VERSION_CONTENT, content2);
// Now delete the version history
VersionHistory deletedVersionHistory = this.authoringService.deleteAllVersions(reference);
assertNotNull(deletedVersionHistory);
assertNull(deletedVersionHistory.getVersions());
// Check the version history
VersionHistory versionHistory3 = this.authoringService.getVersionHistory(reference);
assertNotNull(versionHistory3);
assertNull(versionHistory3.getVersions());
}
}

View File

@@ -0,0 +1,199 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.example.webservice.classification;
import javax.xml.rpc.ServiceException;
import junit.framework.AssertionFailedError;
import org.alfresco.example.webservice.BaseWebServiceSystemTest;
import org.alfresco.example.webservice.types.Category;
import org.alfresco.example.webservice.types.ClassDefinition;
import org.alfresco.example.webservice.types.Classification;
import org.alfresco.example.webservice.types.Predicate;
import org.alfresco.example.webservice.types.Reference;
import org.alfresco.util.GUID;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.configuration.FileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class ClassificationServiceSystemTest extends BaseWebServiceSystemTest
{
private static Log logger = LogFactory
.getLog(ClassificationServiceSystemTest.class);
private ClassificationServiceSoapBindingStub classificationService;
@Override
protected void setUp() throws Exception
{
super.setUp();
try
{
EngineConfiguration config = new FileProvider(getResourcesDir(),
"client-deploy.wsdd");
this.classificationService = (ClassificationServiceSoapBindingStub) new ClassificationServiceLocator(
config).getClassificationService();
} catch (ServiceException jre)
{
if (jre.getLinkedCause() != null)
{
jre.getLinkedCause().printStackTrace();
}
throw new AssertionFailedError("JAX-RPC ServiceException caught: "
+ jre);
}
assertNotNull("contentService is null", this.classificationService);
// Time out after a minute
this.classificationService.setTimeout(60000);
}
/**
* Tests the getClassifications service method
*
* @throws Exception
*/
public void testGetClassifications() throws Exception
{
Classification[] classifications = this.classificationService
.getClassifications(getStore());
assertNotNull(classifications);
assertTrue((classifications.length != 0));
Classification classification = classifications[0];
assertNotNull(classification.getTitle());
assertNotNull(classification.getRootCategory());
assertNotNull(classification.getRootCategory().getId());
assertNotNull(classification.getRootCategory().getTitle());
if (logger.isDebugEnabled() == true)
{
for (Classification item : classifications)
{
logger.debug(
"Classification '" +
item.getTitle() +
"' with root category '" +
item.getRootCategory().getTitle() +
"'");
}
}
}
/**
* Tests the getChildCategories service method
*
* @throws Exception
*/
public void testGetChildCategories() throws Exception
{
Classification[] classifications = this.classificationService.getClassifications(getStore());
Reference parentCategory = classifications[0].getRootCategory().getId();
Category[] categories = this.classificationService.getChildCategories(parentCategory);
assertNotNull(categories);
assertTrue((categories.length != 0));
Category item = categories[0];
assertNotNull(item.getId());
assertNotNull(item.getTitle());
if (logger.isDebugEnabled() == true)
{
for (Category category : categories)
{
logger.debug(
"Sub-category '" +
category.getTitle() +
"'");
}
}
}
/**
* Tests the getCategories and setCategories service methods
*
* @throws Exception
*/
public void testGetAndSetCategories() throws Exception
{
Classification[] classifications = this.classificationService.getClassifications(getStore());
String classification = classifications[0].getClassification();
Reference category = classifications[0].getRootCategory().getId();
Reference reference = createContentAtRoot(GUID.generate(), "Any old content.");
Predicate predicate = convertToPredicate(reference);
// First try and get the categories for a uncategoried node
CategoriesResult[] result1 = this.classificationService.getCategories(predicate);
assertNotNull(result1);
assertEquals(1, result1.length);
assertNull(result1[0].getCategories());
AppliedCategory appliedCategory = new AppliedCategory();
appliedCategory.setCategories(new Reference[]{category});
appliedCategory.setClassification(classification);
AppliedCategory[] appliedCategories = new AppliedCategory[]{appliedCategory};
// Now classify the node
CategoriesResult[] result2 = this.classificationService.setCategories(predicate, appliedCategories);
assertNotNull(result2);
assertEquals(1, result2.length);
// Now get the value back
CategoriesResult[] result3 = this.classificationService.getCategories(predicate);
assertNotNull(result3);
assertEquals(1, result3.length);
CategoriesResult categoryResult = result3[0];
assertEquals(reference.getUuid(), categoryResult.getNode().getUuid());
AppliedCategory[] appCats = categoryResult.getCategories();
assertNotNull(appCats);
assertEquals(1, appCats.length);
AppliedCategory appCat = appCats[0];
assertEquals(classification, appCat.getClassification());
Reference[] refs = appCat.getCategories();
assertNotNull(refs);
assertEquals(1, refs.length);
Reference ref = refs[0];
assertEquals(category.getUuid(), ref.getUuid());
// TODO test multiple classifiations
// TODO test clearing the classifications
// TODO test updating the classifications
}
/**
* Tests the describeClassification service method
*
* @throws Exception
*/
public void testDescribeClassification() throws Exception
{
Classification[] classifications = this.classificationService.getClassifications(getStore());
String classification = classifications[0].getClassification();
ClassDefinition classDefinition = this.classificationService.describeClassification(classification);
assertNotNull(classDefinition);
}
}

View File

@@ -0,0 +1,153 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.example.webservice.content;
import org.alfresco.example.webservice.BaseWebServiceSystemTest;
import org.alfresco.example.webservice.repository.UpdateResult;
import org.alfresco.example.webservice.types.CML;
import org.alfresco.example.webservice.types.CMLCreate;
import org.alfresco.example.webservice.types.ContentFormat;
import org.alfresco.example.webservice.types.NamedValue;
import org.alfresco.example.webservice.types.ParentReference;
import org.alfresco.example.webservice.types.Predicate;
import org.alfresco.example.webservice.types.Reference;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class ContentServiceSystemTest extends BaseWebServiceSystemTest
{
private static final String CONTENT = "This is a small piece of content to test the create service call";
private static final String UPDATED_CONTENT = "This is some updated content to test the write service call";
private String fileName = "unit-test.txt";
public void testContentService()
throws Exception
{
ParentReference parentRef = new ParentReference();
parentRef.setStore(getStore());
parentRef.setUuid(getRootNodeReference().getUuid());
parentRef.setAssociationType(ContentModel.ASSOC_CHILDREN.toString());
parentRef.setChildName(ContentModel.ASSOC_CHILDREN.toString());
NamedValue[] properties = new NamedValue[]{new NamedValue(ContentModel.PROP_NAME.toString(), this.fileName)};
CMLCreate create = new CMLCreate("1", parentRef, ContentModel.TYPE_CONTENT.toString(), properties);
CML cml = new CML();
cml.setCreate(new CMLCreate[]{create});
UpdateResult[] result = this.repositoryService.update(cml);
Reference newContentNode = result[0].getDestination();
String property = ContentModel.PROP_CONTENT.toString();
Predicate predicate = new Predicate(new Reference[]{newContentNode}, getStore(), null);
// First check a node that has no content set
Content[] contents1 = this.contentService.read(predicate, property);
assertNotNull(contents1);
assertEquals(1, contents1.length);
Content content1 = contents1[0];
assertNotNull(content1);
assertEquals(0, content1.getLength());
assertEquals(newContentNode.getUuid(), content1.getNode().getUuid());
assertEquals(property, content1.getProperty());
assertNull(content1.getUrl());
assertNull(content1.getFormat());
// Write content
Content content2 = this.contentService.write(newContentNode, property, CONTENT.getBytes(), new ContentFormat(MimetypeMap.MIMETYPE_TEXT_PLAIN, "UTF-8"));
assertNotNull(content2);
assertTrue((content2.getLength() > 0));
assertEquals(newContentNode.getUuid(), content2.getNode().getUuid());
assertEquals(property, content2.getProperty());
assertNotNull(content2.getUrl());
assertNotNull(content2.getFormat());
ContentFormat format2 = content2.getFormat();
assertEquals(MimetypeMap.MIMETYPE_TEXT_PLAIN, format2.getMimetype());
assertEquals("UTF-8", format2.getEncoding());
assertEquals(CONTENT, getContentAsString(content2.getUrl()));
// Read content
Content[] contents3 = this.contentService.read(predicate, property);
assertNotNull(contents3);
assertEquals(1, contents3.length);
Content content3 = contents3[0];
assertNotNull(content3);
assertTrue((content3.getLength() > 0));
assertEquals(newContentNode.getUuid(), content3.getNode().getUuid());
assertEquals(property, content3.getProperty());
assertNotNull(content3.getUrl());
assertNotNull(content3.getFormat());
ContentFormat format3 = content3.getFormat();
assertEquals(MimetypeMap.MIMETYPE_TEXT_PLAIN, format3.getMimetype());
assertEquals("UTF-8", format3.getEncoding());
assertEquals(CONTENT, getContentAsString(content3.getUrl()));
// Update content
Content content4 = this.contentService.write(newContentNode, property, UPDATED_CONTENT.getBytes(), new ContentFormat(MimetypeMap.MIMETYPE_TEXT_CSS, "UTF-8"));
assertNotNull(content4);
assertTrue((content4.getLength() > 0));
assertEquals(newContentNode.getUuid(), content4.getNode().getUuid());
assertEquals(property, content4.getProperty());
assertNotNull(content4.getUrl());
assertNotNull(content4.getFormat());
ContentFormat format4 = content4.getFormat();
assertEquals(MimetypeMap.MIMETYPE_TEXT_CSS, format4.getMimetype());
assertEquals("UTF-8", format4.getEncoding());
assertEquals(UPDATED_CONTENT, getContentAsString(content4.getUrl()));
// Read updated content
Content[] contents5 = this.contentService.read(predicate, property);
assertNotNull(contents5);
assertEquals(1, contents5.length);
Content content5 = contents5[0];
assertNotNull(content5);
assertTrue((content5.getLength() > 0));
assertEquals(newContentNode.getUuid(), content5.getNode().getUuid());
assertEquals(property, content5.getProperty());
assertNotNull(content5.getUrl());
assertNotNull(content5.getFormat());
ContentFormat format5 = content5.getFormat();
assertEquals(MimetypeMap.MIMETYPE_TEXT_CSS, format5.getMimetype());
assertEquals("UTF-8", format5.getEncoding());
assertEquals(UPDATED_CONTENT, getContentAsString(content5.getUrl()));
// Clear content
Content[] contents6 = this.contentService.clear(predicate, property);
assertNotNull(contents6);
assertEquals(1, contents6.length);
Content content6 = contents6[0];
assertNotNull(content6);
assertEquals(0, content6.getLength());
assertEquals(newContentNode.getUuid(), content6.getNode().getUuid());
assertEquals(property, content6.getProperty());
assertNull(content6.getUrl());
assertNull(content6.getFormat());
// Read cleared content
Content[] contents7 = this.contentService.read(predicate, property);
assertNotNull(contents7);
assertEquals(1, contents7.length);
Content content7 = contents7[0];
assertNotNull(content7);
assertEquals(0, content7.getLength());
assertEquals(newContentNode.getUuid(), content7.getNode().getUuid());
assertEquals(property, content7.getProperty());
assertNull(content7.getUrl());
assertNull(content7.getFormat());
}
}

View File

@@ -0,0 +1,535 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.example.webservice.repository;
import javax.xml.rpc.ServiceException;
import junit.framework.AssertionFailedError;
import org.alfresco.example.webservice.BaseWebServiceSystemTest;
import org.alfresco.example.webservice.WebServiceBootstrapSystemTest;
import org.alfresco.example.webservice.types.CML;
import org.alfresco.example.webservice.types.CMLAddAspect;
import org.alfresco.example.webservice.types.CMLCreate;
import org.alfresco.example.webservice.types.ClassDefinition;
import org.alfresco.example.webservice.types.NamedValue;
import org.alfresco.example.webservice.types.Node;
import org.alfresco.example.webservice.types.NodeDefinition;
import org.alfresco.example.webservice.types.ParentReference;
import org.alfresco.example.webservice.types.Predicate;
import org.alfresco.example.webservice.types.PropertyDefinition;
import org.alfresco.example.webservice.types.Query;
import org.alfresco.example.webservice.types.QueryConfiguration;
import org.alfresco.example.webservice.types.QueryLanguageEnum;
import org.alfresco.example.webservice.types.Reference;
import org.alfresco.example.webservice.types.ResultSet;
import org.alfresco.example.webservice.types.ResultSetRow;
import org.alfresco.example.webservice.types.ResultSetRowNode;
import org.alfresco.example.webservice.types.Store;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.configuration.FileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class RepositoryServiceSystemTest extends BaseWebServiceSystemTest
{
private static Log logger = LogFactory
.getLog(RepositoryServiceSystemTest.class);
private RepositoryServiceSoapBindingStub repoService;
@Override
protected void setUp() throws Exception
{
super.setUp();
try
{
EngineConfiguration config = new FileProvider(getResourcesDir(),
"client-deploy.wsdd");
this.repoService = (RepositoryServiceSoapBindingStub) new RepositoryServiceLocator(
config).getRepositoryService();
} catch (ServiceException jre)
{
if (jre.getLinkedCause() != null)
{
jre.getLinkedCause().printStackTrace();
}
throw new AssertionFailedError("JAX-RPC ServiceException caught: "
+ jre);
}
assertNotNull("repoService is null", this.repoService);
// Time out after a minute
this.repoService.setTimeout(60000);
}
/**
* Tests the getStores method
*
* @throws Exception
*/
public void testGetStores() throws Exception
{
Store[] stores = this.repoService.getStores();
assertNotNull("Stores array should not be null", stores);
assertTrue("There should be at least 1 store", stores.length >= 1);
}
/**
* Tests the query service call
*
* @throws Exception
*/
public void testQuery() throws Exception
{
// Query query = new Query(QueryLanguageEnum.lucene, "*");
Query query = new Query(QueryLanguageEnum.lucene,
"( +@\\{http\\://www.alfresco.org/1.0\\}name:test*) OR TEXT:test*");
QueryResult queryResult = this.repoService.query(getStore(), query,
false);
assertNotNull("queryResult should not be null", queryResult);
ResultSet resultSet = queryResult.getResultSet();
assertNotNull("The result set should not be null", resultSet);
logger.debug("There are " + resultSet.getTotalRowCount() + " rows:");
if (resultSet.getTotalRowCount() > 0)
{
ResultSetRow[] rows = resultSet.getRows();
for (int x = 0; x < rows.length; x++)
{
ResultSetRow row = rows[x];
NamedValue[] columns = row.getColumns();
for (int y = 0; y < columns.length; y++)
{
logger.debug("row " + x + ": "
+ row.getColumns(y).getName() + " = "
+ row.getColumns(y).getValue());
}
}
} else
{
logger.debug("The query returned no results");
fail("The query returned no results");
}
}
/**
* Tests the ability to retrieve the results of a query in batches
*
* @throws Exception
*/
public void testQuerySession() throws Exception
{
// define a query that will return a lot of hits i.e. EVERYTHING
Query query = new Query(QueryLanguageEnum.lucene, "*");
// add the query configuration header to the call
int batchSize = 5;
QueryConfiguration queryCfg = new QueryConfiguration();
queryCfg.setFetchSize(batchSize);
this.repoService.setHeader(new RepositoryServiceLocator()
.getServiceName().getNamespaceURI(), "QueryHeader", queryCfg);
// get the first set of results back
QueryResult queryResult = this.repoService.query(getStore(), query,
false);
assertNotNull("queryResult should not be null", queryResult);
String querySession = queryResult.getQuerySession();
String origQuerySession = querySession;
assertNotNull("querySession should not be null", querySession);
ResultSet resultSet = queryResult.getResultSet();
assertNotNull("The result set should not be null", resultSet);
logger.debug("There are " + resultSet.getTotalRowCount()
+ " rows in total");
logger.debug("There are " + resultSet.getRows().length
+ " rows in the first set");
assertEquals("The result set size should be " + batchSize, batchSize,
resultSet.getRows().length);
// get the next batch of results
queryResult = this.repoService.fetchMore(querySession);
assertNotNull("queryResult should not be null", queryResult);
querySession = queryResult.getQuerySession();
assertNotNull("querySession should not be null", querySession);
ResultSet resultSet2 = queryResult.getResultSet();
assertNotNull("The second result set should not be null", resultSet2);
logger.debug("There are " + resultSet2.getRows().length
+ " rows in the second set");
assertEquals("The result set size should be " + batchSize, batchSize,
resultSet2.getRows().length);
// get the rest of the results to make sure it finishes properly
while (querySession != null)
{
queryResult = this.repoService.fetchMore(querySession);
assertNotNull("queryResult returned in loop should not be null",
queryResult);
querySession = queryResult.getQuerySession();
logger.debug("There were another "
+ queryResult.getResultSet().getRows().length
+ " rows returned");
}
// try and fetch some more results and we should get an error
try
{
queryResult = this.repoService.fetchMore(origQuerySession);
fail("We should have seen an error as all the results have been returned");
} catch (Exception e)
{
// expected
}
}
/**
* Tests the queryParents service method
*
* @throws Exception
*/
public void testQueryParents() throws Exception
{
// query for all the child nodes of the root
Reference node = getRootNodeReference();
String rootId = node.getUuid();
QueryResult rootChildren = this.repoService.queryChildren(node);
assertNotNull("rootChildren should not be null", rootChildren);
ResultSet rootChildrenResults = rootChildren.getResultSet();
assertNotNull("rootChildrenResults should not be null",
rootChildrenResults);
assertTrue("There should be at least one child of the root node",
rootChildrenResults.getRows().length > 0);
// get hold of the id of the first child
ResultSetRow firstRow = rootChildrenResults.getRows(0);
assertNotNull("getColumns() should not return null", firstRow
.getColumns());
String id = firstRow.getNode().getId();
logger.debug("Retrieving parents for first node found: " + id + "....");
node = new Reference();
node.setStore(getStore());
node.setUuid(id);
QueryResult parents = this.repoService.queryParents(node);
assertNotNull("parents should not be null", parents);
ResultSet parentsResults = parents.getResultSet();
assertNotNull("parentsResults should not be null", parentsResults);
assertTrue("There should be at least one parent", parentsResults
.getRows().length > 0);
// show the results
boolean rootFound = false;
ResultSetRow[] rows = parentsResults.getRows();
for (int x = 0; x < rows.length; x++)
{
ResultSetRow row = rows[x];
assertNotNull("getColumns() should not return null", row
.getColumns());
ResultSetRowNode rowNode = row.getNode();
String nodeId = rowNode.getId();
logger.debug("parent node = " + nodeId + ", type = "
+ rowNode.getType());
if (nodeId.equals(rootId) == true)
{
rootFound = true;
}
}
// make sure the root node was one of the parents
assertTrue("The root node was not found as one of the parents!!",
rootFound);
}
/*
* Tests the queryAssociated service method
*
* @throws Exception
*/
public void testQueryAssociated() throws Exception
{
Reference contentRef = this.getContentReference();
Association association = new Association(QName.createQName(NamespaceService.CONTENT_MODEL_PREFIX, "translations").toString(), AssociationDirectionEnum.target);
QueryResult result = this.repoService.queryAssociated(contentRef, new Association[]{association});
assertNotNull(result);
assertNotNull(result.getResultSet());
assertNotNull(result.getResultSet().getRows());
assertEquals(1, result.getResultSet().getRows().length);
}
/**
* Tests the describe service method
*
* @throws Exception
*/
public void testDescribe() throws Exception
{
// get hold of a node we know some info about so we can test the
// returned values (the Alfresco Tutorial PDF)
Query query = new Query(QueryLanguageEnum.lucene,
"( +@\\{http\\://www.alfresco.org/1.0\\}name:test*) OR TEXT:test*");
QueryResult queryResult = this.repoService.query(getStore(), query,
false);
assertNotNull("queryResult should not be null", queryResult);
ResultSet resultSet = queryResult.getResultSet();
assertNotNull("The result set should not be null", resultSet);
assertTrue("There should be at least one result", resultSet
.getTotalRowCount() > 0);
String id = resultSet.getRows(0).getNode().getId();
assertNotNull("Id of Alfresco Tutorial PDF should not be null", id);
// create a predicate object to to send to describe method
Reference ref = new Reference();
ref.setStore(getStore());
ref.setUuid(id);
Predicate predicate = new Predicate(new Reference[] { ref }, null, null);
// make the service call
NodeDefinition[] nodeDefs = this.repoService.describe(predicate);
assertNotNull("nodeDefs should not be null", nodeDefs);
assertTrue("There should only be one result", nodeDefs.length == 1);
// get the result
NodeDefinition nodeDef = nodeDefs[0];
assertNotNull("The nodeDef should not be null", nodeDef);
ClassDefinition typeDef = nodeDef.getType();
assertNotNull("Type definition should not be null", typeDef);
assertEquals("Type name is incorrect",
"{http://www.alfresco.org/model/content/1.0}content", typeDef
.getName());
assertEquals("Superclass type name is incorrect",
"{http://www.alfresco.org/model/content/1.0}cmobject", typeDef
.getSuperClass());
assertEquals("Type title is incorrect", "Content", typeDef.getTitle());
assertEquals("Type description is incorrect", "Base Content Object", typeDef
.getDescription());
assertFalse("Type is an aspect and it shouldn't be", typeDef
.isIsAspect());
assertNull("There should not be any associations", typeDef
.getAssociations());
assertNotNull("Properties should not be null", typeDef.getProperties());
assertEquals("There should be 2 properties", 2,
typeDef.getProperties().length);
// check the name and type of each of the properties
assertEquals("Property1 name is incorrect",
"{http://www.alfresco.org/model/content/1.0}content", typeDef
.getProperties(0).getName());
assertEquals("Property1 type name is incorrect",
"{http://www.alfresco.org/model/dictionary/1.0}content", typeDef
.getProperties(0).getDataType());
assertEquals("Property5 name is incorrect",
"{http://www.alfresco.org/model/content/1.0}name", typeDef
.getProperties(1).getName());
assertEquals("Property5 type name is incorrect",
"{http://www.alfresco.org/model/dictionary/1.0}text", typeDef
.getProperties(1).getDataType());
// check the aspects
ClassDefinition[] aspects = nodeDef.getAspects();
assertNotNull("aspects should not be null", aspects);
assertEquals("There should be 2 aspects", 2, aspects.length);
// check the first aspect
ClassDefinition aspect1 = aspects[0];
assertEquals("Aspect1 name is incorrect",
"{http://www.alfresco.org/model/system/1.0}referenceable",
aspect1.getName());
assertTrue("Aspect1 should be an aspect", aspect1.isIsAspect());
assertNotNull("Aspect1 should have properties", aspect1.getProperties());
assertEquals("Aspect1 has wrong number of properties", 3, aspect1
.getProperties().length);
// check the second aspect
ClassDefinition aspect2 = aspects[1];
assertEquals("Aspect2 name is incorrect",
"{http://www.alfresco.org/model/content/1.0}auditable", aspect2
.getName());
assertTrue("Aspect2 should be an aspect", aspect2.isIsAspect());
assertNotNull("Aspect2 should have properties", aspect2.getProperties());
assertEquals("Aspect2 has wrong number of properties", 5, aspect2
.getProperties().length);
}
/**
* Tests passing a query in the predicate to return items to describe
*
* @throws Exception
*/
public void testPredicateQuery() throws Exception
{
// define a query to add to the predicate (get everything that mentions
// 'test')
Query query = new Query(QueryLanguageEnum.lucene,
"( +@\\{http\\://www.alfresco.org/1.0\\}name:test*) OR TEXT:test*");
Predicate predicate = new Predicate();
predicate.setQuery(query);
predicate.setStore(getStore());
// call the service and make sure we get some details back
NodeDefinition[] nodeDefs = this.repoService.describe(predicate);
assertNotNull("nodeDefs should not be null", nodeDefs);
assertTrue("There should be at least one result", nodeDefs.length > 0);
NodeDefinition nodeDef = nodeDefs[0];
assertNotNull("The nodeDef should not be null", nodeDef);
ClassDefinition typeDef = nodeDef.getType();
assertNotNull("Type definition should not be null", typeDef);
logger.debug("type name = " + typeDef.getName());
logger.debug("is aspect = " + typeDef.isIsAspect());
PropertyDefinition[] propDefs = typeDef.getProperties();
if (propDefs != null)
{
logger.debug("There are " + propDefs.length + " properties:");
for (int x = 0; x < propDefs.length; x++)
{
PropertyDefinition propDef = propDefs[x];
logger.debug("name = " + propDef.getName() + " type = "
+ propDef.getDataType());
}
}
}
/**
* Tests the use of a path within a reference
*
* @throws Exception
*/
public void testPathReference() throws Exception
{
// setup a predicate to find the test folder using an xpath
Reference ref = new Reference();
ref.setStore(getStore());
ref.setPath("//*[@cm:name = '"
+ WebServiceBootstrapSystemTest.FOLDER_NAME + "']");
Predicate predicate = new Predicate();
predicate.setNodes(new Reference[] { ref });
// call the service and make sure we get some details back
NodeDefinition[] nodeDefs = this.repoService.describe(predicate);
assertNotNull("nodeDefs should not be null", nodeDefs);
assertTrue("There should be at least one result", nodeDefs.length > 0);
NodeDefinition nodeDef = nodeDefs[0];
assertNotNull("The nodeDef should not be null", nodeDef);
ClassDefinition typeDef = nodeDef.getType();
assertNotNull("Type definition should not be null", typeDef);
logger.debug("type name = " + typeDef.getName());
assertEquals("Type is incorrect",
"{http://www.alfresco.org/model/content/1.0}folder", typeDef
.getName());
logger.debug("is aspect = " + typeDef.isIsAspect());
assertFalse("Item should not be an aspect", typeDef.isIsAspect());
PropertyDefinition[] propDefs = typeDef.getProperties();
if (propDefs != null)
{
logger.debug("There are " + propDefs.length + " properties:");
for (int x = 0; x < propDefs.length; x++)
{
PropertyDefinition propDef = propDefs[x];
logger.debug("name = " + propDef.getName() + " type = "
+ propDef.getDataType());
}
}
}
/**
* Tests the update service method
*
* @throws Exception
*/
public void testUpdate() throws Exception
{
CMLCreate create = new CMLCreate();
create.setId("id1");
create.setType(ContentModel.TYPE_CONTENT.toString());
ParentReference parentReference = new ParentReference();
parentReference.setAssociationType(ContentModel.ASSOC_CHILDREN
.toString());
parentReference.setChildName(ContentModel.ASSOC_CHILDREN.toString());
parentReference.setStore(getStore());
parentReference.setUuid(getRootNodeReference().getUuid());
create.setParent(parentReference);
create.setProperty(new NamedValue[] {
new NamedValue(
ContentModel.PROP_NAME.toString(),
"name"),
new NamedValue(
ContentModel.PROP_CONTENT.toString(),
new ContentData(null, MimetypeMap.MIMETYPE_TEXT_PLAIN, 0L, "UTF-8").toString())
});
CMLAddAspect aspect = new CMLAddAspect();
aspect.setAspect(ContentModel.ASPECT_VERSIONABLE.toString());
aspect.setWhere_id("id1");
CML cml = new CML();
cml.setCreate(new CMLCreate[]{create});
cml.setAddAspect(new CMLAddAspect[]{aspect});
UpdateResult[] results = this.repoService.update(cml);
assertNotNull(results);
assertEquals(2, results.length);
}
public void testGet()
throws Exception
{
Predicate predicate = new Predicate(null, getStore(), null);
Node[] nodes = this.repoService.get(predicate);
assertNotNull(nodes);
assertEquals(1, nodes.length);
Node rootNode = nodes[0];
assertEquals(getRootNodeReference().getUuid(), rootNode.getReference().getUuid());
logger.debug("Root node type = " + rootNode.getType());
String aspects = "";
for (String aspect : rootNode.getAspects())
{
aspects += aspect + ", ";
}
logger.debug("Root node aspects = " + aspects);
for (NamedValue prop : rootNode.getProperties())
{
logger.debug("Root node property " + prop.getName() + " = " + prop.getValue());
}
}
}

View File

@@ -0,0 +1,142 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.example.webservice.sample;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.xml.rpc.ServiceException;
import org.alfresco.example.webservice.authentication.AuthenticationResult;
import org.alfresco.example.webservice.authentication.AuthenticationServiceLocator;
import org.alfresco.example.webservice.authentication.AuthenticationServiceSoapBindingStub;
import org.alfresco.example.webservice.repository.RepositoryServiceLocator;
import org.alfresco.example.webservice.repository.RepositoryServiceSoapBindingStub;
import org.alfresco.example.webservice.types.Store;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.configuration.FileProvider;
import org.apache.ws.security.WSPasswordCallback;
/**
* Web service sample 1.
* <p>
* Connect to the reposity and get a list of all the stores available in the repository.
*
* @author Roy Wetherall
*/
public class WebServiceSample1 implements CallbackHandler
{
/** Admin user name and password used to connect to the repository */
public static final String USERNAME = "admin";
public static final String PASSWORD = "admin";
/** The current ticket */
public static String currentTicket;
/** WS security information */
public static final String WS_SECURITY_INFO =
"<deployment xmlns='http://xml.apache.org/axis/wsdd/' xmlns:java='http://xml.apache.org/axis/wsdd/providers/java'>" +
" <transport name='http' pivot='java:org.apache.axis.transport.http.HTTPSender'/>" +
" <globalConfiguration >" +
" <requestFlow >" +
" <handler type='java:org.apache.ws.axis.security.WSDoAllSender' >" +
" <parameter name='action' value='UsernameToken'/>" +
" <parameter name='user' value='ticket'/>" +
" <parameter name='passwordCallbackClass' value='org.alfresco.example.webservice.sample.WebServiceSample1'/>" +
" <parameter name='passwordType' value='PasswordText'/>" +
" </handler>" +
" </requestFlow >" +
" </globalConfiguration>" +
"</deployment>";
/**
* Connect to the respository and print out the names of the available
*
* @param args
*/
public static void main(String[] args)
throws Exception
{
AuthenticationServiceSoapBindingStub authenticationService = (AuthenticationServiceSoapBindingStub)new AuthenticationServiceLocator().getAuthenticationService();
// Start the session
AuthenticationResult result = authenticationService.startSession(WebServiceSample1.USERNAME, WebServiceSample1.PASSWORD);
WebServiceSample1.currentTicket = result.getTicket();
// Get a reference to the respository web service
RepositoryServiceSoapBindingStub repositoryService = getRepositoryWebService();
// Get array of stores available in the repository
Store[] stores = repositoryService.getStores();
if (stores == null)
{
// NOTE: empty array are returned as a null object, this is a issue with the generated web service code.
System.out.println("There are no stores avilable in the repository.");
}
else
{
// Output the names of all the stores available in the repository
System.out.println("The following stores are available in the repository:");
for (Store store : stores)
{
System.out.println(store.getAddress());
}
}
// End the session
authenticationService.endSession();
}
/**
* Get the respository web service.
*
* @return the respository web service
* @throws ServiceException Service Exception
*/
public static RepositoryServiceSoapBindingStub getRepositoryWebService() throws ServiceException
{
// Create the respository service, adding the WS security header information
EngineConfiguration config = new FileProvider(new ByteArrayInputStream(WebServiceSample1.WS_SECURITY_INFO.getBytes()));
RepositoryServiceLocator repositoryServiceLocator = new RepositoryServiceLocator(config);
RepositoryServiceSoapBindingStub repositoryService = (RepositoryServiceSoapBindingStub)repositoryServiceLocator.getRepositoryService();
return repositoryService;
}
/**
* The implementation of the passwrod call back used by the WS Security
*
* @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
*/
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
{
for (int i = 0; i < callbacks.length; i++)
{
if (callbacks[i] instanceof WSPasswordCallback)
{
WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
pc.setPassword(currentTicket);
}
else
{
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
}
}
}
}

View File

@@ -0,0 +1,154 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.example.webservice.sample;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
import org.alfresco.example.webservice.authentication.AuthenticationResult;
import org.alfresco.example.webservice.authentication.AuthenticationServiceLocator;
import org.alfresco.example.webservice.authentication.AuthenticationServiceSoapBindingStub;
import org.alfresco.example.webservice.repository.QueryResult;
import org.alfresco.example.webservice.repository.RepositoryFault;
import org.alfresco.example.webservice.repository.RepositoryServiceSoapBindingStub;
import org.alfresco.example.webservice.types.NamedValue;
import org.alfresco.example.webservice.types.Query;
import org.alfresco.example.webservice.types.QueryLanguageEnum;
import org.alfresco.example.webservice.types.Reference;
import org.alfresco.example.webservice.types.ResultSet;
import org.alfresco.example.webservice.types.ResultSetRow;
import org.alfresco.example.webservice.types.Store;
import org.alfresco.example.webservice.types.StoreEnum;
/**
* Web service sample 2
* <p>
* This sample shows how to execute a search using the repository web service and how to
* query for a nodes parents.
*
* @author Roy Wetherall
*/
public class WebServiceSample2
{
/**
* Main function
*/
public static void main(String[] args)
throws Exception
{
// Get the authentication service
AuthenticationServiceSoapBindingStub authenticationService = (AuthenticationServiceSoapBindingStub)new AuthenticationServiceLocator().getAuthenticationService();
// Start the session
AuthenticationResult result = authenticationService.startSession(WebServiceSample1.USERNAME, WebServiceSample1.PASSWORD);
WebServiceSample1.currentTicket = result.getTicket();
// Execute the search sample
executeSearch();
// End the session
authenticationService.endSession();
}
/**
* Executes a sample query and provides an example of using a parent query.
*
* @return returns a reference to a folder that is the parent of the search results
* ( used in further samples)
* @throws ServiceException Service exception
* @throws RemoteException Remove exception
* @throws RepositoryFault Repository fault
*/
public static Reference executeSearch() throws ServiceException, RemoteException, RepositoryFault
{
Reference parentReference = null;
// Get a reference to the respository web service
RepositoryServiceSoapBindingStub repositoryService = WebServiceSample1.getRepositoryWebService();
// Create a store object referencing the main spaced store
Store store = new Store(StoreEnum.workspace, "SpacesStore");
// Create a query object, looking for all items with alfresco in the name of text
Query query = new Query(QueryLanguageEnum.lucene, "( +@\\{http\\://www.alfresco.org/1.0\\}name:alfresco*) OR TEXT:alfresco*");
// Execute the query
QueryResult queryResult = repositoryService.query(store, query, false);
// Display the results
ResultSet resultSet = queryResult.getResultSet();
ResultSetRow[] rows = resultSet.getRows();
if (rows == null)
{
System.out.println("No query results found.");
}
else
{
System.out.println("Results from query:");
outputResultSet(rows);
// Get the id of the first result
String firstResultId = rows[0].getNode().getId();
Reference reference = new Reference(store, firstResultId, null);
// Get the parent(s) of the first result
QueryResult parentQueryResult = repositoryService.queryParents(reference);
// Get the parent of the first result
ResultSet parentResultSet = parentQueryResult.getResultSet();
ResultSetRow[] parentRows = parentResultSet.getRows();
if (parentRows == null)
{
System.out.println("No query results found.");
}
else
{
System.out.println("Results from parent query:");
outputResultSet(parentRows);
// Return the first parent (we can use in other samples)
String firstParentId = parentRows[0].getNode().getId();
parentReference = new Reference(store, firstParentId, null);
}
}
return parentReference;
}
/**
* Helper method to output the rows contained within a result set
*
* @param rows an array of rows
*/
public static void outputResultSet(ResultSetRow[] rows)
{
for (int x = 0; x < rows.length; x++)
{
ResultSetRow row = rows[x];
NamedValue[] columns = row.getColumns();
for (int y = 0; y < columns.length; y++)
{
System.out.println("row " + x + ": "
+ row.getColumns(y).getName() + " = "
+ row.getColumns(y).getValue());
}
}
}
}

View File

@@ -0,0 +1,185 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.example.webservice.sample;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import javax.xml.rpc.ServiceException;
import org.alfresco.example.webservice.authentication.AuthenticationResult;
import org.alfresco.example.webservice.authentication.AuthenticationServiceLocator;
import org.alfresco.example.webservice.authentication.AuthenticationServiceSoapBindingStub;
import org.alfresco.example.webservice.content.Content;
import org.alfresco.example.webservice.content.ContentServiceLocator;
import org.alfresco.example.webservice.content.ContentServiceSoapBindingStub;
import org.alfresco.example.webservice.repository.UpdateResult;
import org.alfresco.example.webservice.types.CML;
import org.alfresco.example.webservice.types.CMLCreate;
import org.alfresco.example.webservice.types.ContentFormat;
import org.alfresco.example.webservice.types.NamedValue;
import org.alfresco.example.webservice.types.ParentReference;
import org.alfresco.example.webservice.types.Predicate;
import org.alfresco.example.webservice.types.Reference;
import org.alfresco.example.webservice.types.Store;
import org.alfresco.example.webservice.types.StoreEnum;
import org.alfresco.model.ContentModel;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.configuration.FileProvider;
/**
* Web service sample 3
* <p>
* This web service sample shows how new content can be added to the repository and how content
* can be read and updated via the web service API.
*
* @author Roy Wetherall
*/
public class WebServiceSample3
{
/** Content strings used in the sample */
private static final String INITIAL_CONTENT = "This is some new content that I am adding to the repository";
private static final String UPDATED_CONTENT = "This is the updated content";
/** The type of the association we are creating to the new content */
private static final String ASSOC_CONTAINS = "{http://www.alfresco.org/model/content/1.0}contains";
/**
* Main function
*/
public static void main(String[] args) throws Exception
{
AuthenticationServiceSoapBindingStub authenticationService = (AuthenticationServiceSoapBindingStub)new AuthenticationServiceLocator().getAuthenticationService();
// Start the session
AuthenticationResult result = authenticationService.startSession(WebServiceSample1.USERNAME, WebServiceSample1.PASSWORD);
WebServiceSample1.currentTicket = result.getTicket();
// Get the content service
ContentServiceSoapBindingStub contentService = getContentWebService();
// Create new content in the respository
Reference newContentReference = createNewContent(contentService, "sampleThreeFileOne.txt", INITIAL_CONTENT);
// Read the newly added content from the respository
Store store = new Store(StoreEnum.workspace, "SpacesStore");
Content[] readResult = contentService.read(
new Predicate(new Reference[]{newContentReference}, store, null),
ContentModel.PROP_CONTENT.toString());
Content content = readResult[0];
// Get the content from the download servlet using the URL and display it
System.out.println("The newly added content is:");
System.out.println(getContentAsString(WebServiceSample1.currentTicket, content.getUrl()));
// Update the content with something new
contentService.write(newContentReference, ContentModel.PROP_CONTENT.toString(), UPDATED_CONTENT.getBytes(), null);
// Now output the updated content
Content[] readResult2 = contentService.read(
new Predicate(new Reference[]{newContentReference}, store, null),
ContentModel.PROP_CONTENT.toString());
Content content2 = readResult2[0];
System.out.println("The updated content is:");
System.out.println(getContentAsString(WebServiceSample1.currentTicket, content2.getUrl()));
// End the session
authenticationService.endSession();
}
/**
* Get the content web service
*
* @return content web service
* @throws ServiceException
*/
public static ContentServiceSoapBindingStub getContentWebService() throws ServiceException
{
// Create the content service, adding the WS security header information
EngineConfiguration config = new FileProvider(new ByteArrayInputStream(WebServiceSample1.WS_SECURITY_INFO.getBytes()));
ContentServiceLocator contentServiceLocator = new ContentServiceLocator(config);
ContentServiceSoapBindingStub contentService = (ContentServiceSoapBindingStub)contentServiceLocator.getContentService();
return contentService;
}
/**
* Helper method to create new content.
*
* @param contentService the content web service
* @param content the content itself
* @return a reference to the created content node
* @throws Exception
*/
public static Reference createNewContent(ContentServiceSoapBindingStub contentService, String name, String contentString)
throws Exception
{
// First we'll use the previous sample to get hold of a reference to a space that we can create the content within
Reference reference = WebServiceSample2.executeSearch();
// Create a parent reference, this contains information about the association we are createing to the new content and the
// parent of the new content (the space retrived from the search)
ParentReference parentReference = new ParentReference(ASSOC_CONTAINS, ASSOC_CONTAINS);
parentReference.setStore(reference.getStore());
parentReference.setUuid(reference.getUuid());
// Define the content format for the content we are adding
ContentFormat contentFormat = new ContentFormat("text/plain", "UTF-8");
NamedValue[] properties = new NamedValue[]{new NamedValue(ContentModel.PROP_NAME.toString(), name)};
CMLCreate create = new CMLCreate("1", parentReference, ContentModel.TYPE_CONTENT.toString(), properties);
CML cml = new CML();
cml.setCreate(new CMLCreate[]{create});
UpdateResult[] result = WebServiceSample1.getRepositoryWebService().update(cml);
Reference newContentNode = result[0].getDestination();
Content content = contentService.write(newContentNode, ContentModel.PROP_CONTENT.toString(), contentString.getBytes(), contentFormat);
// Get a reference to the newly created content
return content.getNode();
}
/**
* This method gets the content from the download servlet for a given URL and returns it as a string.
*
* @param ticket the current ticket
* @param strUrl the content URL
* @return the content as a string
* @throws Exception
*/
public static String getContentAsString(String ticket, String strUrl) throws Exception
{
// Add the ticket to the url
strUrl += "?ticket=" + ticket;
// Connect to donwload servlet
StringBuilder readContent = new StringBuilder();
URL url = new URL(strUrl);
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
int read = is.read();
while (read != -1)
{
readContent.append((char)read);
read = is.read();
}
// return content as a string
return readContent.toString();
}
}

View File

@@ -0,0 +1,120 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.example.webservice.sample;
import org.alfresco.example.webservice.authentication.AuthenticationResult;
import org.alfresco.example.webservice.authentication.AuthenticationServiceLocator;
import org.alfresco.example.webservice.authentication.AuthenticationServiceSoapBindingStub;
import org.alfresco.example.webservice.repository.RepositoryServiceSoapBindingStub;
import org.alfresco.example.webservice.repository.UpdateResult;
import org.alfresco.example.webservice.types.CML;
import org.alfresco.example.webservice.types.CMLAddAspect;
import org.alfresco.example.webservice.types.CMLCreate;
import org.alfresco.example.webservice.types.Node;
import org.alfresco.example.webservice.types.ParentReference;
import org.alfresco.example.webservice.types.Predicate;
import org.alfresco.example.webservice.types.Reference;
import org.alfresco.example.webservice.types.Store;
import org.alfresco.example.webservice.types.StoreEnum;
import org.alfresco.model.ContentModel;
/**
* Web service sample 4
* <p>
* This sample shows how to construct and execute CML queries using the respository web service.
*
* @author Roy Wetherall
*/
public class WebServiceSample4
{
/**
* Main function
*/
public static void main(String[] args)
throws Exception
{
// Start the session
AuthenticationServiceSoapBindingStub authenticationService = (AuthenticationServiceSoapBindingStub)new AuthenticationServiceLocator().getAuthenticationService();
AuthenticationResult result = authenticationService.startSession(WebServiceSample1.USERNAME, WebServiceSample1.PASSWORD);
WebServiceSample1.currentTicket = result.getTicket();
// Create a store object referencing the main spaced store
Store store = new Store(StoreEnum.workspace, "SpacesStore");
// Get the repository
RepositoryServiceSoapBindingStub repositoryService = WebServiceSample1.getRepositoryWebService();
Reference folder = getTutorialFolder(store, repositoryService);
// Create the CML structure
// When executed this cml update query will create a new content node beneth the tutorial folder and the add the
// versionable aspect to the newly created node
ParentReference parentReference = new ParentReference(ContentModel.ASSOC_CONTAINS.toString(), ContentModel.ASSOC_CONTAINS.toString());
parentReference.setStore(store);
parentReference.setUuid(folder.getUuid());
CMLCreate create = new CMLCreate("id1", parentReference, ContentModel.TYPE_CONTENT.toString(), null);
CMLAddAspect addAspect = new CMLAddAspect(ContentModel.ASPECT_VERSIONABLE.toString(), null, null, "id1");
CML cml = new CML();
cml.setCreate(new CMLCreate[]{create});
cml.setAddAspect(new CMLAddAspect[]{addAspect});
// Execute the update
UpdateResult[] updateResults = repositoryService.update(cml);
for (UpdateResult updateResult : updateResults)
{
String sourceId = "none";
Reference source = updateResult.getSource();
if (source != null)
{
sourceId = source.getUuid();
}
String destinationId = "none";
Reference destination = updateResult.getDestination();
if (destination != null)
{
destinationId = destination.getUuid();
}
System.out.println(
"Command = " + updateResult.getStatement() +
"; Source = " + sourceId +
"; Destination = " + destinationId);
}
// End the session
authenticationService.endSession();
}
/**
* Get the space immediatly beneth company home call "Alfresco Tutorial"
*
* @param store
* @param repositoryService
* @return
* @throws Exception
*/
public static Reference getTutorialFolder(Store store, RepositoryServiceSoapBindingStub repositoryService)
throws Exception
{
Reference reference = new Reference(store, null, "/app:company_home/*[@cm:name=\"Alfresco Tutorial\"]");
Predicate predicate = new Predicate(new Reference[]{reference}, null, null);
Node[] nodes = repositoryService.get(predicate);
return nodes[0].getReference();
}
}

View File

@@ -0,0 +1,170 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.example.webservice.sample;
import java.io.ByteArrayInputStream;
import javax.xml.rpc.ServiceException;
import org.alfresco.example.webservice.authentication.AuthenticationResult;
import org.alfresco.example.webservice.authentication.AuthenticationServiceLocator;
import org.alfresco.example.webservice.authentication.AuthenticationServiceSoapBindingStub;
import org.alfresco.example.webservice.authoring.AuthoringServiceLocator;
import org.alfresco.example.webservice.authoring.AuthoringServiceSoapBindingStub;
import org.alfresco.example.webservice.authoring.CheckoutResult;
import org.alfresco.example.webservice.content.Content;
import org.alfresco.example.webservice.content.ContentServiceSoapBindingStub;
import org.alfresco.example.webservice.repository.RepositoryServiceSoapBindingStub;
import org.alfresco.example.webservice.types.CML;
import org.alfresco.example.webservice.types.CMLAddAspect;
import org.alfresco.example.webservice.types.ContentFormat;
import org.alfresco.example.webservice.types.NamedValue;
import org.alfresco.example.webservice.types.Predicate;
import org.alfresco.example.webservice.types.Reference;
import org.alfresco.example.webservice.types.Store;
import org.alfresco.example.webservice.types.StoreEnum;
import org.alfresco.example.webservice.types.Version;
import org.alfresco.example.webservice.types.VersionHistory;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.configuration.FileProvider;
/**
* Web service sample 5
* <p>
* This sample shows how to check documents out, check them back in and then view the
* version history.
*
* @author Roy Wetherall
*/
public class WebServiceSample5
{
private final static String INITIAL_CONTENT = "This is the content pror to checkout";
private final static String UPDATED_CONTENT = "This is the updated content";
private final static String VERSIONABLE_ASPECT = "{http://www.alfresco.org/model/content/1.0}versionable";
/**
* Main function
*/
public static void main(String[] args)
throws Exception
{
// Start the session
AuthenticationServiceSoapBindingStub authenticationService = (AuthenticationServiceSoapBindingStub)new AuthenticationServiceLocator().getAuthenticationService();
AuthenticationResult result = authenticationService.startSession(WebServiceSample1.USERNAME, WebServiceSample1.PASSWORD);
WebServiceSample1.currentTicket = result.getTicket();
// Get the content and authoring service
RepositoryServiceSoapBindingStub repositoryService = WebServiceSample1.getRepositoryWebService();
ContentServiceSoapBindingStub contentService = WebServiceSample3.getContentWebService();
AuthoringServiceSoapBindingStub authoringService = WebServiceSample5.getAuthoringWebService();
// Get a reference to a newly created content
Reference contentReference = WebServiceSample3.createNewContent(contentService, "SampleFiveFileOne.txt", INITIAL_CONTENT);
// Add the versionable aspect to the newly created content. This will allows the content to be versioned
makeVersionable(repositoryService, contentReference);
// Checkout the newly created content, placing the working document in the same folder
Predicate itemsToCheckOut = new Predicate(new Reference[]{contentReference}, null, null);
CheckoutResult checkOutResult = authoringService.checkout(itemsToCheckOut, null);
// Get a reference to the working copy
Reference workingCopyReference = checkOutResult.getWorkingCopies()[0];
// Update the content of the working copy
ContentFormat format = new ContentFormat(MimetypeMap.MIMETYPE_TEXT_PLAIN, "UTF-8");
contentService.write(workingCopyReference, ContentModel.PROP_CONTENT.toString(), UPDATED_CONTENT.getBytes(), format);
// Now check the working copy in with a description of the change made that will be recorded in the version history
Predicate predicate = new Predicate(new Reference[]{workingCopyReference}, null, null);
NamedValue[] comments = new NamedValue[]{new NamedValue("description", "The content has been updated")};
authoringService.checkin(predicate, comments, false);
// Output the updated content
Store store = new Store(StoreEnum.workspace, "SpacesStore");
Content[] readResult = contentService.read(
new Predicate(new Reference[]{contentReference}, store, null),
ContentModel.PROP_CONTENT.toString());
Content content = readResult[0];
System.out.println("This is the checked-in content:");
System.out.println(WebServiceSample3.getContentAsString(WebServiceSample1.currentTicket, content.getUrl()));
// Get the version history
System.out.println("The version history:");
VersionHistory versionHistory = authoringService.getVersionHistory(contentReference);
for (Version version : versionHistory.getVersions())
{
// Output the version details
outputVersion(version);
}
// End the session
authenticationService.endSession();
}
/**
* Get a reference to the authoring web service
*
* @return the authoring web service
* @throws ServiceException
*/
public static AuthoringServiceSoapBindingStub getAuthoringWebService() throws ServiceException
{
// Create the content service, adding the WS security header information
EngineConfiguration config = new FileProvider(new ByteArrayInputStream(WebServiceSample1.WS_SECURITY_INFO.getBytes()));
AuthoringServiceLocator authoringServiceLocator = new AuthoringServiceLocator(config);
AuthoringServiceSoapBindingStub authoringService = (AuthoringServiceSoapBindingStub)authoringServiceLocator.getAuthoringService();
return authoringService;
}
/**
* Helper method to make apply the versionable aspect to a given reference
* <p>
* See sample 4 for more CML examples
*
* @param respositoryService the respository service
* @param reference the reference
* @throws Exception
*/
public static void makeVersionable(RepositoryServiceSoapBindingStub respositoryService, Reference reference)
throws Exception
{
// Create the add aspect query object
Predicate predicate = new Predicate(new Reference[]{reference}, null, null);
CMLAddAspect addAspect = new CMLAddAspect(VERSIONABLE_ASPECT, null, predicate, null);
// Create the content management language query
CML cml = new CML();
cml.setAddAspect(new CMLAddAspect[]{addAspect});
// Execute the query, which will add the versionable aspect to the node is question
respositoryService.update(cml);
}
/**
* Helper to output the version details
*
* @param version the version
*/
private static void outputVersion(Version version)
{
System.out.println("Version label = " + version.getLabel() + "; Version description = " + version.getCommentaries()[0].getValue());
}
}

View File

@@ -0,0 +1,139 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.example.webservice.sample;
import java.io.ByteArrayInputStream;
import org.alfresco.example.webservice.authentication.AuthenticationResult;
import org.alfresco.example.webservice.authentication.AuthenticationServiceLocator;
import org.alfresco.example.webservice.authentication.AuthenticationServiceSoapBindingStub;
import org.alfresco.example.webservice.classification.ClassificationServiceLocator;
import org.alfresco.example.webservice.classification.ClassificationServiceSoapBindingStub;
import org.alfresco.example.webservice.repository.QueryResult;
import org.alfresco.example.webservice.repository.RepositoryServiceSoapBindingStub;
import org.alfresco.example.webservice.types.Category;
import org.alfresco.example.webservice.types.Classification;
import org.alfresco.example.webservice.types.Query;
import org.alfresco.example.webservice.types.QueryLanguageEnum;
import org.alfresco.example.webservice.types.Store;
import org.alfresco.example.webservice.types.StoreEnum;
import org.alfresco.repo.search.ISO9075;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.configuration.FileProvider;
/**
* Web service sample 6
* <p>
* Example showing how content can be queried for using categories
*
* @author Roy Wetherall
*/
public class WebServiceSample6
{
/**
* Main function
*/
public static void main(String[] args)
throws Exception
{
// Start the session
AuthenticationServiceSoapBindingStub authenticationService = (AuthenticationServiceSoapBindingStub)new AuthenticationServiceLocator().getAuthenticationService();
AuthenticationResult result = authenticationService.startSession(WebServiceSample1.USERNAME, WebServiceSample1.PASSWORD);
WebServiceSample1.currentTicket = result.getTicket();
// Get the content and authoring service
RepositoryServiceSoapBindingStub repositoryService = WebServiceSample1.getRepositoryWebService();
// Get the classification service
EngineConfiguration config = new FileProvider(new ByteArrayInputStream(WebServiceSample1.WS_SECURITY_INFO.getBytes()));
ClassificationServiceSoapBindingStub classificationService = (ClassificationServiceSoapBindingStub) new ClassificationServiceLocator(config).getClassificationService();
// Create the store reference
Store store = new Store(StoreEnum.workspace, "SpacesStore");
// Get all the classifications
Classification[] classifications = classificationService.getClassifications(store);
// Output some details
System.out.println("All classifications:");
for (Classification classification : classifications)
{
System.out.println(classification.getClassification());
System.out.println("Classification = " + classification.getTitle() + "; Root category = " + classification.getRootCategory().getTitle());
}
// Get the class definition for the classification we are interested in
Classification classification = classifications[0];
// Get the child categories
Category[] categories = null;
if (classifications.length > 0)
{
categories = classificationService.getChildCategories(classifications[0].getRootCategory().getId());
if (categories != null)
{
// Output some details
System.out.println("The child categories of classification '" + classifications[0].getTitle() + "':");
for (Category category : categories)
{
System.out.println("Title = " + category.getTitle());
}
}
else
{
System.out.println("No child categories found.");
}
}
// Now build a path query
StringBuilder pathQuery = new StringBuilder(128);
//pathQuery.append("PATH:\"cm:generalclassifiable/cm:MyTestCategory/cm:One/member\"");
// Encode the root category name
String encodedRoot = ISO9075.encode(classification.getRootCategory().getTitle());
// Build up the search path
if (categories != null && categories.length != 0)
{
for (int i=0; i<categories.length; i++)
{
if (pathQuery.length() != 0)
{
pathQuery.append("OR");
}
String encoded = ISO9075.encode(categories[i].getTitle());
pathQuery.append(" PATH:\"cm:generalclassifiable/cm:" + encodedRoot + "/cm:" + encoded + "/member\" ");
}
}
System.out.println("Query path: " + pathQuery.toString());
// Call the repository service to do search based on category
Query query = new Query(QueryLanguageEnum.lucene, pathQuery.toString());
// Execute the query
QueryResult queryResult = repositoryService.query(store, query, true);
System.out.println("Category query results:");
WebServiceSample2.outputResultSet(queryResult.getResultSet().getRows());
// End the session
authenticationService.endSession();
}
}

View File

@@ -0,0 +1,263 @@
// NOTE: if you change the package location of this class you will need to update the WS_SEURITY_INFO XML as for this example this class
// doubles as the passwordCAllbackClass
package org.alfresco.example.webservice.sample;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.example.webservice.authentication.AuthenticationResult;
import org.alfresco.example.webservice.authentication.AuthenticationServiceLocator;
import org.alfresco.example.webservice.authentication.AuthenticationServiceSoapBindingStub;
import org.alfresco.example.webservice.repository.QueryResult;
import org.alfresco.example.webservice.repository.RepositoryServiceLocator;
import org.alfresco.example.webservice.repository.RepositoryServiceSoapBindingStub;
import org.alfresco.example.webservice.types.NamedValue;
import org.alfresco.example.webservice.types.Node;
import org.alfresco.example.webservice.types.Predicate;
import org.alfresco.example.webservice.types.Query;
import org.alfresco.example.webservice.types.QueryLanguageEnum;
import org.alfresco.example.webservice.types.Reference;
import org.alfresco.example.webservice.types.ResultSet;
import org.alfresco.example.webservice.types.ResultSetRow;
import org.alfresco.example.webservice.types.Store;
import org.alfresco.example.webservice.types.StoreEnum;
import org.alfresco.model.ContentModel;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.configuration.FileProvider;
import org.apache.ws.security.WSPasswordCallback;
public class WebServiceSampleGetRankedContent implements CallbackHandler
{
/** Admin user name and password used to connect to the repository */
public static final String USERNAME = "admin";
public static final String PASSWORD = "admin";
/** The current ticket */
public static String currentTicket;
/** WS security information */
public static final String WS_SECURITY_INFO =
"<deployment xmlns='http://xml.apache.org/axis/wsdd/' xmlns:java='http://xml.apache.org/axis/wsdd/providers/java'>" +
" <transport name='http' pivot='java:org.apache.axis.transport.http.HTTPSender'/>" +
" <globalConfiguration >" +
" <requestFlow >" +
" <handler type='java:org.apache.ws.axis.security.WSDoAllSender' >" +
" <parameter name='action' value='UsernameToken'/>" +
" <parameter name='user' value='ticket'/>" +
" <parameter name='passwordCallbackClass' value='org.alfresco.example.webservice.sample.WebServiceSampleGetRankedContent'/>" +
" <parameter name='passwordType' value='PasswordText'/>" +
" </handler>" +
" </requestFlow >" +
" </globalConfiguration>" +
"</deployment>";
/**
* Main method
*
* @param args
*/
public static void main(String[] args)
{
WebServiceSampleGetRankedContent sample = new WebServiceSampleGetRankedContent();
List<ContentResult> results = sample.getRankedContent("Alfresco Tutorial", "alfresco*");
// Output the results for visual inspection
int iCount = 1;
for (ContentResult result : results)
{
System.out.println("Result " + iCount + ": " + result.toString());
iCount ++;
}
}
/**
* Get a list of ordered results of documents in the space specified matching the search
* text provided.
*
* @param spaceName the name of the space (immediatly beneth the company home space) to search
* @param searchValue the FTS search value
* @return list of results
*/
public List<ContentResult> getRankedContent(String spaceName, String searchValue)
{
List<ContentResult> results = new ArrayList<ContentResult>();
try
{
// Get the authentication service
AuthenticationServiceSoapBindingStub authenticationService = (AuthenticationServiceSoapBindingStub)new AuthenticationServiceLocator().getAuthenticationService();
// Start the session
AuthenticationResult authenticationResult = authenticationService.startSession(WebServiceSample1.USERNAME, WebServiceSample1.PASSWORD);
WebServiceSampleGetRankedContent.currentTicket = authenticationResult.getTicket();
// Create the respository service, adding the WS security header information
EngineConfiguration config = new FileProvider(new ByteArrayInputStream(WebServiceSampleGetRankedContent.WS_SECURITY_INFO.getBytes()));
RepositoryServiceLocator repositoryServiceLocator = new RepositoryServiceLocator(config);
RepositoryServiceSoapBindingStub repositoryService = (RepositoryServiceSoapBindingStub)repositoryServiceLocator.getRepositoryService();
// Create a store object referencing the main spaced store
Store store = new Store(StoreEnum.workspace, "SpacesStore");
// Get a reference to the space we have named
Reference reference = new Reference(store, null, "/app:company_home/*[@cm:name=\"" + spaceName + "\"]");
Predicate predicate = new Predicate(new Reference[]{reference}, null, null);
Node[] nodes = repositoryService.get(predicate);
// Create a query object, looking for all items with alfresco in the name of text
Query query = new Query(
QueryLanguageEnum.lucene,
"+PARENT:\"workspace://SpacesStore/"+ nodes[0].getReference().getUuid() + "\" +TEXT:\"" + searchValue + "\"");
// Execute the query
QueryResult queryResult = repositoryService.query(store, query, false);
// Display the results
ResultSet resultSet = queryResult.getResultSet();
ResultSetRow[] rows = resultSet.getRows();
if (rows != null)
{
// Get the infomation from the result set
for(ResultSetRow row : rows)
{
String nodeId = row.getNode().getId();
ContentResult contentResult = new ContentResult(nodeId);
for (NamedValue namedValue : row.getColumns())
{
if (namedValue.getName().endsWith(ContentModel.PROP_CREATED.toString()) == true)
{
contentResult.setCreateDate(namedValue.getValue());
}
else if (namedValue.getName().endsWith(ContentModel.PROP_NAME.toString()) == true)
{
contentResult.setName(namedValue.getValue());
}
else if (namedValue.getName().endsWith(ContentModel.PROP_DESCRIPTION.toString()) == true)
{
contentResult.setDescription(namedValue.getValue());
}
else if (namedValue.getName().endsWith(ContentModel.PROP_CONTENT.toString()) == true)
{
// We could go to the content service and ask for the content to get the URL but to save time we
// might as well dig the content URL out of the results.
String contentString = namedValue.getValue();
String[] values = contentString.split("[|=]");
contentResult.setUrl(values[1]);
}
}
results.add(contentResult);
}
}
// End the session
authenticationService.endSession();
}
catch (Exception serviceException)
{
throw new AlfrescoRuntimeException("Unable to perform search.", serviceException);
}
return results;
}
/**
* Security callback handler
*/
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
{
for (int i = 0; i < callbacks.length; i++)
{
if (callbacks[i] instanceof WSPasswordCallback)
{
WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
pc.setPassword(WebServiceSampleGetRankedContent.currentTicket);
}
else
{
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
}
}
}
/**
* Class to contain the information about the result from the query
*/
public class ContentResult
{
private String id;
private String name;
private String description;
private String url;
private String createDate;
public ContentResult(String id)
{
this.id = id;
}
public String getCreateDate()
{
return createDate;
}
public void setCreateDate(String createDate)
{
this.createDate = createDate;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public String getId()
{
return id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getUrl()
{
return url;
}
public void setUrl(String url)
{
this.url = url;
}
@Override
public String toString()
{
return "id=" + this.id +
"; name=" + this.name +
"; description=" + this.description +
"; created=" + this.createDate +
"; url=" + this.url;
}
}
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
import javax.servlet.http.HttpServletResponse;
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.NodeRef;
/**
* Implements the WebDAV COPY and MOVE methods
*
* @author Derek Hulley
*/
public abstract class AbstractMoveOrCopyMethod extends HierarchicalMethod
{
/**
* Default constructor
*/
public AbstractMoveOrCopyMethod()
{
}
/**
* Implement the move or copy, depending on the implementation
*
* @param fileFolderService the service to do the work
* @param sourceNodeRef the node to copy or move
* @param destParentNodeRef the destination parent
* @param name the name of the file or folder
* @throws Exception
*/
protected abstract void moveOrCopy(
FileFolderService fileFolderService,
NodeRef sourceNodeRef,
NodeRef destParentNodeRef,
String name) throws Exception;
/**
* Exceute the request
*
* @exception WebDAVServerException
*/
protected final void executeImpl() throws WebDAVServerException, Exception
{
FileFolderService fileFolderService = getFileFolderService();
NodeRef rootNodeRef = getRootNodeRef();
String servletPath = getServletPath();
// Debug
if (logger.isDebugEnabled())
{
logger.debug("Copy from " + getPath() + " to " + getDestinationPath());
}
// the source must exist
String sourcePath = getPath();
FileInfo sourceInfo = null;
try
{
sourceInfo = getDAVHelper().getNodeForPath(rootNodeRef, sourcePath, servletPath);
}
catch (FileNotFoundException e)
{
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
}
// the destination parent must exist
String destPath = getDestinationPath();
FileInfo destParentInfo = null;
try
{
destParentInfo = getDAVHelper().getParentNodeForPath(rootNodeRef, destPath, servletPath);
}
catch (FileNotFoundException e)
{
if (logger.isDebugEnabled())
{
logger.debug("Destination parent folder doesn't exist: " + destPath);
}
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
}
// check for the existence of the destination node
FileInfo destInfo = null;
try
{
destInfo = getDAVHelper().getNodeForPath(rootNodeRef, destPath, servletPath);
if (!hasOverWrite())
{
if (logger.isDebugEnabled())
{
logger.debug("Destination exists but overwrite is not allowed");
}
// it exists and we may not overwrite
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
}
// delete the destination node if it is not the same as the source node
if (!destInfo.getNodeRef().equals(sourceInfo.getNodeRef()))
{
// attempting to move or copy onto another node
fileFolderService.delete(destInfo.getNodeRef());
}
else
{
// it is a copy or move onto itself
}
}
catch (FileNotFoundException e)
{
// destination doesn't exist
}
NodeRef sourceNodeRef = sourceInfo.getNodeRef();
NodeRef destParentNodeRef = destParentInfo.getNodeRef();
String name = getDAVHelper().splitPath(destPath)[1];
moveOrCopy(fileFolderService, sourceNodeRef, destParentNodeRef, name);
// Set the response status
if (destInfo == null)
{
m_response.setStatus(HttpServletResponse.SC_CREATED);
}
else
{
m_response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Implements the WebDAV COPY method
*
* @author Derek Hulley
*/
public class CopyMethod extends AbstractMoveOrCopyMethod
{
/**
* Default constructor
*/
public CopyMethod()
{
}
@Override
protected void moveOrCopy(
FileFolderService fileFolderService,
NodeRef sourceNodeRef,
NodeRef destParentNodeRef,
String name) throws Exception
{
fileFolderService.copy(sourceNodeRef, destParentNodeRef, name);
}
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
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.NodeRef;
/**
* Implements the WebDAV DELETE method
*
* @author gavinc
*/
public class DeleteMethod extends WebDAVMethod
{
/**
* Default constructor
*/
public DeleteMethod()
{
}
/**
* Parse the request headers
*
* @exception WebDAVServerException
*/
protected void parseRequestHeaders() throws WebDAVServerException
{
// Nothing to do in this method
}
/**
* Parse the request body
*
* @exception WebDAVServerException
*/
protected void parseRequestBody() throws WebDAVServerException
{
// Nothing to do in this method
}
/**
* Execute the request
*
* @exception WebDAVServerException
*/
protected void executeImpl() throws WebDAVServerException, Exception
{
if (logger.isDebugEnabled())
{
logger.debug("WebDAV DELETE: " + getPath());
}
FileFolderService fileFolderService = getFileFolderService();
NodeRef rootNodeRef = getRootNodeRef();
String path = getPath();
List<String> pathElements = getDAVHelper().splitAllPaths(path);
FileInfo fileInfo = null;
try
{
// get the node to delete
fileInfo = fileFolderService.resolveNamePath(rootNodeRef, pathElements);
}
catch (FileNotFoundException e)
{
if (logger.isDebugEnabled())
{
logger.debug("Node not found: " + getPath());
}
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
}
// delete it
fileFolderService.delete(fileInfo.getNodeRef());
}
}

View File

@@ -0,0 +1,478 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
import java.io.IOException;
import java.io.Writer;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;
import javax.servlet.http.HttpServletResponse;
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.ContentReader;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.repository.datatype.TypeConverter;
/**
* Implements the WebDAV GET method
*
* @author gavinc
*/
public class GetMethod extends WebDAVMethod
{
// Request parameters
private ArrayList ifMatchTags = null;
private ArrayList ifNoneMatchTags = null;
private Date m_ifModifiedSince = null;
private Date m_ifUnModifiedSince = null;
protected boolean m_returnContent = true;
/**
* Default constructor
*/
public GetMethod()
{
}
/**
* Parse the request headers
*
* @exception WebDAVServerException
*/
protected void parseRequestHeaders() throws WebDAVServerException
{
// If the range header is present output a warning, add support later
String strRange = m_request.getHeader(WebDAV.HEADER_RANGE);
if (strRange != null && strRange.length() > 0)
{
logger.warn("Range header (" + strRange + ") not supported");
}
// Capture all the If headers, process later
String strIfMatch = m_request.getHeader(WebDAV.HEADER_IF_MATCH);
if (strIfMatch != null && strIfMatch.length() > 0)
{
ifMatchTags = parseETags(strIfMatch);
}
String strIfNoneMatch = m_request.getHeader(WebDAV.HEADER_IF_NONE_MATCH);
if (strIfNoneMatch != null && strIfNoneMatch.length() > 0)
{
ifNoneMatchTags = parseETags(strIfNoneMatch);
}
// Parse the dates
SimpleDateFormat dateFormat = new SimpleDateFormat(WebDAV.HEADER_IF_DATE_FORMAT);
String strIfModifiedSince = m_request.getHeader(WebDAV.HEADER_IF_MODIFIED_SINCE);
if (strIfModifiedSince != null && strIfModifiedSince.length() > 0)
{
try
{
m_ifModifiedSince = dateFormat.parse(strIfModifiedSince);
}
catch (ParseException e)
{
logger.warn("Failed to parse If-Modified-Since date of " + strIfModifiedSince);
}
}
String strIfUnModifiedSince = m_request.getHeader(WebDAV.HEADER_IF_UNMODIFIED_SINCE);
if (strIfUnModifiedSince != null && strIfUnModifiedSince.length() > 0)
{
try
{
m_ifUnModifiedSince = dateFormat.parse(strIfUnModifiedSince);
}
catch (ParseException e)
{
logger.warn("Failed to parse If-Unmodified-Since date of " + strIfUnModifiedSince);
}
}
}
/**
* Parse the request body
*
* @exception WebDAVServerException
*/
protected void parseRequestBody() throws WebDAVServerException
{
// Nothing to do in this method
}
/**
* Exceute the WebDAV request
*
* @exception WebDAVServerException
*/
protected void executeImpl() throws WebDAVServerException, Exception
{
FileFolderService fileFolderService = getFileFolderService();
NodeRef rootNodeRef = getRootNodeRef();
String path = getPath();
String servletPath = getServletPath();
FileInfo nodeInfo = null;
try
{
nodeInfo = getDAVHelper().getNodeForPath(rootNodeRef, path, servletPath);
}
catch (FileNotFoundException e)
{
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
}
// Check if the node is a folder
if (nodeInfo.isFolder())
{
// is content required
if (!m_returnContent)
{
// it is a folder and no content is required
throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST);
}
// Generate a folder listing
generateDirectoryListing(nodeInfo);
}
else
{
NodeRef pathNodeRef = nodeInfo.getNodeRef();
// Return the node details, and content if requested, check that the node passes the pre-conditions
checkPreConditions(nodeInfo);
// Build the response header
m_response.setHeader(WebDAV.HEADER_ETAG, getDAVHelper().makeQuotedETag(pathNodeRef));
Date modifiedDate = nodeInfo.getModifiedDate();
if (modifiedDate != null)
{
long modDate = DefaultTypeConverter.INSTANCE.longValue(modifiedDate);
m_response.setHeader(WebDAV.HEADER_LAST_MODIFIED, WebDAV.formatHeaderDate(modDate));
}
ContentReader reader = fileFolderService.getReader(nodeInfo.getNodeRef());
if (reader != null)
{
// there is content associated with the node
m_response.setHeader(WebDAV.HEADER_CONTENT_LENGTH, "" + reader.getSize());
m_response.setHeader(WebDAV.HEADER_CONTENT_TYPE, reader.getMimetype());
if (m_returnContent)
{
// copy the content to the response output stream
reader.getContent(m_response.getOutputStream());
}
}
}
}
/**
* Checks the If header conditions
*
* @param nodeInfo the node to check
* @throws WebDAVServerException if a pre-condition is not met
*/
private void checkPreConditions(FileInfo nodeInfo) throws WebDAVServerException
{
// Make an etag for the node
String strETag = getDAVHelper().makeQuotedETag(nodeInfo.getNodeRef());
TypeConverter typeConv = DefaultTypeConverter.INSTANCE;
// Check the If-Match header, don't send any content back if none of the tags in
// the list match the etag, and the wildcard is not present
if (ifMatchTags != null)
{
if (ifMatchTags.contains(WebDAV.ASTERISK) == false && ifMatchTags.contains(strETag) == false)
{
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
}
}
// Check the If-None-Match header, don't send any content back if any of the tags
// in the list match the etag, or the wildcard is present
if (ifNoneMatchTags != null)
{
if (ifNoneMatchTags.contains(WebDAV.ASTERISK) || ifNoneMatchTags.contains(strETag))
{
throw new WebDAVServerException(HttpServletResponse.SC_NOT_MODIFIED);
}
}
// Check the modified since list, if the If-None-Match header was not specified
if (m_ifModifiedSince != null && ifNoneMatchTags == null)
{
Date lastModifiedDate = nodeInfo.getModifiedDate();
long fileLastModified = lastModifiedDate != null ? typeConv.longValue(lastModifiedDate) : 0L;
long modifiedSince = m_ifModifiedSince.getTime();
if (fileLastModified != 0L && fileLastModified <= modifiedSince)
{
throw new WebDAVServerException(HttpServletResponse.SC_NOT_MODIFIED);
}
}
// Check the un-modified since list
if (m_ifUnModifiedSince != null)
{
Date lastModifiedDate = nodeInfo.getModifiedDate();
long fileLastModified = lastModifiedDate != null ? typeConv.longValue(lastModifiedDate) : 0L;
long unModifiedSince = m_ifUnModifiedSince.getTime();
if (fileLastModified >= unModifiedSince)
{
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
}
}
}
/**
* Parses the given ETag header into a list of separate ETags
*
* @param strETagHeader The header to parse
* @return A list of ETags
*/
private ArrayList parseETags(String strETagHeader)
{
ArrayList<String> list = new ArrayList<String>();
StringTokenizer tokenizer = new StringTokenizer(strETagHeader, WebDAV.HEADER_VALUE_SEPARATOR);
while (tokenizer.hasMoreTokens())
{
list.add(tokenizer.nextToken().trim());
}
return list;
}
/**
* Generates a HTML representation of the contents of the path represented by the given node
*
* @param fileInfo the file to use
*/
private void generateDirectoryListing(FileInfo fileInfo)
{
FileFolderService fileFolderService = getFileFolderService();
Writer writer = null;
try
{
writer = m_response.getWriter();
// Get the list of child nodes for the parent node
List<FileInfo> childNodeInfos = fileFolderService.list(fileInfo.getNodeRef());
// Send back the start of the HTML
writer.write("<html><head><title>Alfresco Content Repository</title>");
writer.write("<style>");
writer.write("body { font-family: Arial, Helvetica; font-size: 12pt; background-color: white; }\n");
writer.write("table { font-family: Arial, Helvetica; font-size: 12pt; background-color: white; }\n");
writer.write(".listingTable { border: solid black 1px; }\n");
writer.write(".textCommand { font-family: verdana; font-size: 10pt; }\n");
writer.write(".textLocation { font-family: verdana; font-size: 11pt; font-weight: bold; color: #2a568f; }\n");
writer.write(".textData { font-family: verdana; font-size: 10pt; }\n");
writer.write(".tableHeading { font-family: verdana; font-size: 10pt; font-weight: bold; color: white; background-color: #2a568f; }\n");
writer.write(".rowOdd { background-color: #eeeeee; }\n");
writer.write(".rowEven { background-color: #dddddd; }\n");
writer.write("</style></head>\n");
writer.flush();
// Send back the table heading
writer.write("<body>\n");
writer.write("<table cellspacing='2' cellpadding='3' border='0' width='100%'>\n");
writer.write("<tr><td colspan='3' class='textLocation'>Directory listing for ");
writer.write(getPath());
writer.write("</td></tr>\n");
writer.write("<tr><td height='10'></td></tr></table>");
writer.write("<table cellspacing='2' cellpadding='3' border='0' width='100%' class='listingTable'>\n");
writer.write("<tr><td class='tableHeading' width='*'>Name</td>");
writer.write("<td class='tableHeading' width='10%'>Size</td>");
writer.write("<td class='tableHeading' width='20%'>Modified</td>");
writer.write("</tr>");
// Get the URL for the root path
String rootURL = WebDAV.getURLForPath(m_request, getPath(), true);
if (rootURL.endsWith(WebDAVHelper.PathSeperator) == false)
rootURL = rootURL + WebDAVHelper.PathSeperator;
// Start with a link to the parent folder so we can navigate back up, unless we are at the root level
if (fileInfo.getNodeRef().equals(getRootNodeRef()) == false)
{
writer.write("<tr class='rowOdd'>");
writer.write("<td class='textData'><a href=\"");
// Strip the last folder from the path
String[] paths = getDAVHelper().splitPath(rootURL.substring(0, rootURL.length() - 1));
writer.write(paths[0]);
writer.write("\">");
writer.write("[Up a level]</a>");
writer.write("</tr>\n");
}
// Send back what we have generated so far
writer.flush();
int rowId = 0;
for (FileInfo childNodeInfo : childNodeInfos)
{
// Output the details for the current node
writer.write("<tr class='");
if (rowId++ % 2 == 0)
{
writer.write("rowOdd");
}
else
{
writer.write("rowEven");
}
writer.write("'><td class='textData'><a href=\"");
writer.write(rootURL);
String fname = childNodeInfo.getName();
writer.write(fname);
writer.write("\">");
writer.write(fname);
writer.write("</a>");
writer.write("</td><td class='textData'>");
if (fileInfo.isFolder())
{
writer.write(formatSize("0"));
}
else
{
ContentReader reader = fileFolderService.getReader(childNodeInfo.getNodeRef());
long fsize = 0L;
if ( reader != null)
{
fsize = reader.getSize();
}
writer.write(formatSize("" + fsize));
}
writer.write("</td><td class='textData'>");
Date modifiedDate = childNodeInfo.getModifiedDate();
if (modifiedDate != null)
{
writer.write(WebDAV.formatHeaderDate(DefaultTypeConverter.INSTANCE.longValue(modifiedDate)));
}
else
{
writer.write("");
}
writer.write("</td>");
writer.write("</tr>\n");
writer.flush();
}
}
catch (Throwable e)
{
logger.error(e);
if (writer != null)
{
try
{
writer.write("<table><tr><td style='color:red'>");
writer.write("An error occurred whilst generating the directory listing, ");
writer.write("please contact the system administrator.</td></tr></table>");
writer.flush();
}
catch (IOException ioe)
{
}
}
}
}
/**
* Formats the given size for display in a directory listing
*
* @param strSize The content size
* @return The formatted size
*/
private String formatSize(String strSize)
{
String strFormattedSize = strSize;
int length = strSize.length();
if (length < 4)
{
strFormattedSize = strSize + " bytes";
}
else if (length >= 4 && length < 7)
{
String strLeft = strSize.substring(0, length - 3);
String strRight = strSize.substring(length - 3, length - 2);
StringBuffer buffer = new StringBuffer(strLeft);
if (!strRight.equals("0"))
{
buffer.append(".");
buffer.append(strRight);
}
buffer.append(" Kb");
strFormattedSize = buffer.toString();
}
else
{
String strLeft = strSize.substring(0, length - 6);
String strRight = strSize.substring(length - 6, length - 5);
StringBuffer buffer = new StringBuffer(strLeft);
if (!strRight.equals("0"))
{
buffer.append(".");
buffer.append(strRight);
}
buffer.append(" Mb");
strFormattedSize = buffer.toString();
}
return strFormattedSize;
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
/**
* Implements the WebDAV HEAD method
*
* @author gavinc
*/
public class HeadMethod extends GetMethod
{
/**
* Default constructor
*/
public HeadMethod()
{
// Do everything the GET request does apart from returning the content
m_returnContent = false;
}
}

View File

@@ -0,0 +1,217 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
import java.net.MalformedURLException;
import java.net.URL;
import javax.servlet.http.HttpServletResponse;
/**
* Abstract base class for the hierarchical methods COPY and MOVE
*
* @author gavinc
*/
public abstract class HierarchicalMethod extends WebDAVMethod
{
// Request parameters
protected String m_strDestinationPath;
protected boolean m_overwrite = false;
/**
* Default constructor
*/
public HierarchicalMethod()
{
}
/**
* Return the destination path
*
* @return String
*/
public final String getDestinationPath()
{
return m_strDestinationPath;
}
/**
* Return the overwrite setting
*
* @return boolean
*/
public final boolean hasOverWrite()
{
return m_overwrite;
}
/**
* Parse the request headers
*
* @exception WebDAVServerException
*/
protected void parseRequestHeaders() throws WebDAVServerException
{
// Get the destination path for the copy
String strDestination = m_request.getHeader(WebDAV.HEADER_DESTINATION);
if (logger.isDebugEnabled())
logger.debug("Parsing Destination header: " + strDestination);
if (strDestination != null && strDestination.length() > 0)
{
int offset = -1;
if (strDestination.startsWith("http://"))
{
// Check that the URL is on this server and refers to the WebDAV
// path, if not then return an error
checkDestinationPath(strDestination);
// Set the offset to the start of the
offset = 7;
}
else if (strDestination.startsWith("https://"))
{
// Check that the URL is on this server and refers to the WebDAV
// path, if not then return an error
checkDestinationPath(strDestination);
// Set the offset to the start of the
offset = 8;
}
// Strip the start of the path if not a relative path
if (offset != -1)
{
offset = strDestination.indexOf(WebDAV.PathSeperator, offset);
if (offset != -1)
{
String strPath = strDestination.substring(offset);
String servletPath = m_request.getServletPath();
offset = strPath.indexOf(servletPath);
if (offset != -1)
strPath = strPath.substring(offset + servletPath.length());
m_strDestinationPath = WebDAV.decodeURL(strPath);
}
}
}
// Failed to fix the destination path, return an error
if (m_strDestinationPath == null)
{
logger.warn("Failed to parse the Destination header: " + strDestination);
throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST);
}
// Check if the copy should overwrite an existing file
String strOverwrite = m_request.getHeader(WebDAV.HEADER_OVERWRITE);
if (strOverwrite != null && strOverwrite.equals(WebDAV.T))
{
m_overwrite = true;
}
}
/**
* Parse the request body
*
* @exception WebDAVServerException
*/
protected void parseRequestBody() throws WebDAVServerException
{
// NOTE: Hierarchical methods do have a body to define what should
// happen
// to the properties when they are moved or copied, however, this
// feature is not implemented by many servers, including ours!!
}
/**
* Check that the destination path is on this server and is a valid WebDAV
* path for this server
*
* @param path String
* @exception WebDAVServerException
*/
protected final void checkDestinationPath(String path) throws WebDAVServerException
{
try
{
// Parse the URL
URL url = new URL(path);
// Check if the path is on this WebDAV server
boolean localPath = true;
if (url.getPort() != -1 && url.getPort() != m_request.getLocalPort())
{
// Debug
if (logger.isDebugEnabled())
logger.debug("Destination path, different server port");
localPath = false;
}
else if (url.getHost().equals(m_request.getLocalName()) == false
&& url.getHost().equals(m_request.getLocalAddr()) == false)
{
// Debug
if (logger.isDebugEnabled())
logger.debug("Destination path, different server name/address");
localPath = false;
}
else if (url.getPath().indexOf(m_request.getServletPath()) == -1)
{
// Debug
if (logger.isDebugEnabled())
logger.debug("Destination path, different serlet path");
localPath = false;
}
// If the URL does not refer to this WebDAV server throw an
// exception
if (localPath != true)
throw new WebDAVServerException(HttpServletResponse.SC_BAD_GATEWAY);
}
catch (MalformedURLException ex)
{
// Debug
if (logger.isDebugEnabled())
logger.debug("Bad destination path, " + path);
throw new WebDAVServerException(HttpServletResponse.SC_BAD_GATEWAY);
}
}
}

View File

@@ -0,0 +1,297 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.lock.LockStatus;
import org.alfresco.service.cmr.lock.LockType;
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.NodeRef;
import org.dom4j.io.XMLWriter;
/**
* Implements the WebDAV LOCK method
*
* @author gavinc
*/
public class LockMethod extends WebDAVMethod
{
private String m_strLockToken = null;
private int m_timeoutDuration = WebDAV.DEPTH_INFINITY;
/**
* Default constructor
*/
public LockMethod()
{
}
/**
* Check if the lock token is valid
*
* @return boolean
*/
protected final boolean hasLockToken()
{
return m_strLockToken != null ? true : false;
}
/**
* Return the lock token of an existing lock
*
* @return String
*/
protected final String getLockToken()
{
return m_strLockToken;
}
/**
* Return the lock timeout, in minutes
*
* @return int
*/
protected final int getLockTimeout()
{
return m_timeoutDuration;
}
/**
* Parse the request headers
*
* @exception WebDAVServerException
*/
protected void parseRequestHeaders() throws WebDAVServerException
{
// Get the lock token, if any
m_strLockToken = parseIfHeader();
// Get the lock timeout value
String strTimeout = m_request.getHeader(WebDAV.HEADER_TIMEOUT);
// If the timeout header starts with anything other than Second
// leave the timeout as the default
if (strTimeout != null && strTimeout.startsWith(WebDAV.SECOND))
{
try
{
// Some clients send header as Second-180 Seconds so we need to
// look for the space
int idx = strTimeout.indexOf(" ");
if (idx != -1)
{
// Get the bit after Second- and before the space
strTimeout = strTimeout.substring(WebDAV.SECOND.length(), idx);
}
else
{
// The string must be in the correct format
strTimeout = strTimeout.substring(WebDAV.SECOND.length());
}
m_timeoutDuration = Integer.parseInt(strTimeout);
}
catch (Exception e)
{
// Warn about the parse failure and leave the timeout as the
// default
logger.warn("Failed to parse Timeout header: " + strTimeout);
}
}
// DEBUG
if (logger.isDebugEnabled())
logger.debug("Lock lockToken=" + getLockToken() + ", timeout=" + getLockTimeout());
}
/**
* Parse the request body
*
* @exception WebDAVServerException
*/
protected void parseRequestBody() throws WebDAVServerException
{
// NOTE: There is a body for lock requests which contain the
// type of lock to apply and the lock owner but we will
// ignore these settings so don't bother reading the body
}
/**
* Exceute the request
*
* @exception WebDAVServerException
*/
protected void executeImpl() throws WebDAVServerException, Exception
{
FileFolderService fileFolderService = getFileFolderService();
String path = getPath();
NodeRef rootNodeRef = getRootNodeRef();
// Get the active user
String userName = getDAVHelper().getAuthenticationService().getCurrentUserName();
if (logger.isDebugEnabled())
{
logger.debug("Locking node: \n" +
" user: " + userName + "\n" +
" path: " + path);
}
FileInfo lockNodeInfo = null;
try
{
// Check if the path exists
lockNodeInfo = getDAVHelper().getNodeForPath(getRootNodeRef(), getPath(), m_request.getServletPath());
}
catch (FileNotFoundException e)
{
// need to create it
String[] splitPath = getDAVHelper().splitPath(path);
// check
if (splitPath[1].length() == 0)
{
throw new WebDAVServerException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
List<String> dirPathElements = getDAVHelper().splitAllPaths(splitPath[0]);
FileInfo dirInfo = fileFolderService.makeFolders(rootNodeRef, dirPathElements, ContentModel.TYPE_FOLDER);
if (dirInfo == null)
{
throw new WebDAVServerException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
// create the file
lockNodeInfo = fileFolderService.create(dirInfo.getNodeRef(), splitPath[1], ContentModel.TYPE_CONTENT);
if (logger.isDebugEnabled())
{
logger.debug("Created new node for lock: \n" +
" path: " + path + "\n" +
" node: " + lockNodeInfo);
}
}
// Check if this is a new lock or a refresh
if (hasLockToken())
{
// Refresh an existing lock
refreshLock(lockNodeInfo.getNodeRef(), userName);
}
else
{
// Create a new lock
createLock(lockNodeInfo.getNodeRef(), userName);
}
// We either created a new lock or refreshed an existing lock, send back the lock details
generateResponse(lockNodeInfo.getNodeRef(), userName);
}
/**
* Create a new lock
*
* @param lockNode NodeRef
* @param userName String
* @exception WebDAVServerException
*/
private final void createLock(NodeRef lockNode, String userName) throws WebDAVServerException
{
LockService lockService = getLockService();
// Check the lock status of the node
LockStatus lockSts = lockService.getLockStatus(lockNode);
// DEBUG
if (logger.isDebugEnabled())
logger.debug("Create lock status=" + lockSts);
if (lockSts == LockStatus.LOCKED || lockSts == LockStatus.LOCK_OWNER)
{
// Indicate that the resource is already locked
throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED);
}
// Lock the node
lockService.lock(lockNode, LockType.WRITE_LOCK, getLockTimeout());
}
/**
* Refresh an existing lock
*
* @param lockNode NodeRef
* @param userName String
* @exception WebDAVServerException
*/
private final void refreshLock(NodeRef lockNode, String userName) throws WebDAVServerException
{
LockService lockService = getLockService();
// Check the lock status of the node
LockStatus lockSts = lockService.getLockStatus(lockNode);
// DEBUG
if (logger.isDebugEnabled())
logger.debug("Refresh lock status=" + lockSts);
if (lockSts != LockStatus.LOCK_OWNER)
{
// Indicate that the resource is already locked
throw new WebDAVServerException(WebDAV.WEBDAV_SC_LOCKED);
}
// Update the expiry for the lock
lockService.lock(lockNode, LockType.WRITE_LOCK, getLockTimeout());
}
/**
* Generates the XML lock discovery response body
*/
private void generateResponse(NodeRef lockNode, String userName) throws Exception
{
XMLWriter xml = createXMLWriter();
xml.startDocument();
String nsdec = generateNamespaceDeclarations(null);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_MULTI_STATUS + nsdec, WebDAV.XML_NS_MULTI_STATUS + nsdec,
getDAVHelper().getNullAttributes());
// Output the lock details
generateLockDiscoveryXML(xml, lockNode);
// Close off the XML
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_MULTI_STATUS, WebDAV.XML_NS_MULTI_STATUS);
// Send the XML back to the client
m_response.setStatus(HttpServletResponse.SC_OK);
xml.flush();
}
}

View File

@@ -0,0 +1,133 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
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.NodeRef;
import org.w3c.dom.Document;
/**
* Implements the WebDAV MKCOL method
*
* @author gavinc
*/
public class MkcolMethod extends WebDAVMethod
{
/**
* Default constructor
*/
public MkcolMethod()
{
}
/**
* Parse the request headers
*
* @Exception WebDAVServerException
*/
protected void parseRequestHeaders() throws WebDAVServerException
{
// Nothing to do in this method
}
/**
* Parse the request body
*
* @exception WebDAVServerException
*/
protected void parseRequestBody() throws WebDAVServerException
{
// There should not be a body with the MKCOL request
Document body = getRequestBodyAsDocument();
if (body != null)
{
throw new WebDAVServerException(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
}
}
/**
* Exceute the request
*
* @exception WebDAVServerException
*/
protected void executeImpl() throws WebDAVServerException, Exception
{
FileFolderService fileFolderService = getFileFolderService();
// see if it exists
try
{
getDAVHelper().getNodeForPath(getRootNodeRef(), getPath(), getServletPath());
// already exists
throw new WebDAVServerException(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
catch (FileNotFoundException e)
{
// it doesn't exist
}
// Trim the last path component and check if the parent path exists
String parentPath = getPath();
int lastPos = parentPath.lastIndexOf(WebDAVHelper.PathSeperator);
NodeRef parentNodeRef = null;
if ( lastPos == 0)
{
// Create new folder at root
parentPath = WebDAVHelper.PathSeperator;
parentNodeRef = getRootNodeRef();
}
else if (lastPos != -1)
{
// Trim the last path component
parentPath = parentPath.substring(0, lastPos + 1);
try
{
FileInfo parentFileInfo = getDAVHelper().getNodeForPath(getRootNodeRef(), parentPath, m_request.getServletPath());
parentNodeRef = parentFileInfo.getNodeRef();
}
catch (FileNotFoundException e)
{
// parent path is missing
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
}
}
else
{
// Looks like a bad path
throw new WebDAVServerException(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
// Get the new folder name
String folderName = getPath().substring(lastPos + 1);
// Create the new folder node
fileFolderService.create(parentNodeRef, folderName, ContentModel.TYPE_FOLDER);
// Return a success status
m_response.setStatus(HttpServletResponse.SC_CREATED);
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Implements the WebDAV MOVE method
*
* @author Derek Hulley
*/
public class MoveMethod extends AbstractMoveOrCopyMethod
{
/**
* Default constructor
*/
public MoveMethod()
{
}
protected void moveOrCopy(
FileFolderService fileFolderService,
NodeRef sourceNodeRef,
NodeRef destParentNodeRef,
String name) throws Exception
{
fileFolderService.move(sourceNodeRef, destParentNodeRef, name);
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
/**
* Implements the WebDAV OPTIONS method
*
* @author Gavin Cornwell
*/
public class OptionsMethod extends WebDAVMethod
{
private static final String DAV_HEADER = "DAV";
private static final String DAV_HEADER_CONTENT = "1,2";
private static final String ALLOW_HEADER = "Allow";
private static final String MS_HEADER = "MS-Author-Via";
private static final String FILE_METHODS = "OPTIONS, GET, HEAD, POST, DELETE, PROPFIND, COPY, MOVE, LOCK, UNLOCK";
private static final String COLLECTION_METHODS = FILE_METHODS + ", PUT";
/**
* Default constructor
*/
public OptionsMethod()
{
}
/**
* Parse the request header fields
*
* @exception WebDAVServerException
*/
protected void parseRequestHeaders() throws WebDAVServerException
{
// Nothing to do in this method
}
/**
* Parse the request main body
*
* @exception WebDAVServerException
*/
protected void parseRequestBody() throws WebDAVServerException
{
// Nothing to do in this method
}
/**
* Perform the main request processing
*
* @exception WebDAVServerException
*/
protected void executeImpl() throws WebDAVServerException
{
boolean isFolder;
try
{
FileInfo fileInfo = getDAVHelper().getNodeForPath(getRootNodeRef(), getPath(), getServletPath());
isFolder = fileInfo.isFolder();
}
catch (FileNotFoundException e)
{
// Do nothing; just default to a folder
isFolder = true;
}
// Add the header to advertise the level of support the server has
m_response.addHeader(DAV_HEADER, DAV_HEADER_CONTENT);
// Add the proprietary Microsoft header to make Microsoft clients behave
m_response.addHeader(MS_HEADER, DAV_HEADER);
// Add the header to show what methods are allowed
m_response.addHeader(ALLOW_HEADER, isFolder ? COLLECTION_METHODS : FILE_METHODS);
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
/**
* Implements the WebDAV POST method
*
* @author Gavin Cornwell
*/
public class PostMethod extends PutMethod
{
/**
* Default constructor
*/
public PostMethod()
{
}
}

View File

@@ -0,0 +1,905 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.lock.LockStatus;
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.NodeRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.repository.datatype.TypeConverter;
import org.alfresco.service.namespace.QName;
import org.dom4j.DocumentHelper;
import org.dom4j.io.XMLWriter;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.AttributesImpl;
/**
* Implements the WebDAV PROPFIND method
*
* @author Gavin Cornwell
*/
public class PropFindMethod extends WebDAVMethod
{
// Request types
private static final int GET_ALL_PROPS = 0;
private static final int GET_NAMED_PROPS = 1;
private static final int FIND_PROPS = 2;
// Find depth and request type
private int m_depth = WebDAV.DEPTH_INFINITY;
private int m_mode = GET_ALL_PROPS;
// Requested properties
private ArrayList<WebDAVProperty> m_properties = null;
// Available namespaces list
private HashMap<String, String> m_namespaces = null;
/**
* Default constructor
*/
public PropFindMethod()
{
m_namespaces = new HashMap<String, String>();
}
/**
* Return the property find depth
*
* @return int
*/
public final int getDepth()
{
return m_depth;
}
/**
* Return the find mode
*
* @return int
*/
public final int getMode()
{
return m_mode;
}
/**
* Parse the request headers
*
* @exception WebDAVServerException
*/
protected void parseRequestHeaders() throws WebDAVServerException
{
// Store the Depth header as this is used by several WebDAV methods
String strDepth = m_request.getHeader(WebDAV.HEADER_DEPTH);
if (strDepth != null && strDepth.length() > 0)
{
if (strDepth.equals(WebDAV.ZERO))
{
m_depth = WebDAV.DEPTH_0;
}
else if (strDepth.equals(WebDAV.ONE))
{
m_depth = WebDAV.DEPTH_1;
}
else
{
m_depth = WebDAV.DEPTH_INFINITY;
}
}
}
/**
* Parse the request body
*
* @exception WebDAVServerException
*/
protected void parseRequestBody() throws WebDAVServerException
{
Document body = getRequestBodyAsDocument();
if (body != null)
{
Element rootElement = body.getDocumentElement();
NodeList childList = rootElement.getChildNodes();
Node node = null;
for (int i = 0; i < childList.getLength(); i++)
{
Node currentNode = childList.item(i);
switch (currentNode.getNodeType())
{
case Node.TEXT_NODE:
break;
case Node.ELEMENT_NODE:
if (currentNode.getNodeName().endsWith(WebDAV.XML_ALLPROP))
{
m_mode = GET_ALL_PROPS;
}
else if (currentNode.getNodeName().endsWith(WebDAV.XML_PROP))
{
m_mode = GET_NAMED_PROPS;
node = currentNode;
}
else if (currentNode.getNodeName().endsWith(WebDAV.XML_PROPNAME))
{
m_mode = FIND_PROPS;
}
break;
}
}
if (m_mode == GET_NAMED_PROPS)
{
m_properties = new ArrayList<WebDAVProperty>();
childList = node.getChildNodes();
for (int i = 0; i < childList.getLength(); i++)
{
Node currentNode = childList.item(i);
switch (currentNode.getNodeType())
{
case Node.TEXT_NODE:
break;
case Node.ELEMENT_NODE:
m_properties.add(createProperty(currentNode));
break;
}
}
}
}
}
/**
* Exceute the main WebDAV request processing
*
* @exception WebDAVServerException
*/
protected void executeImpl() throws WebDAVServerException, Exception
{
m_response.setStatus(WebDAV.WEBDAV_SC_MULTI_STATUS);
FileFolderService fileFolderService = getFileFolderService();
FileInfo pathNodeInfo = null;
try
{
// Check that the path exists
pathNodeInfo = getDAVHelper().getNodeForPath(getRootNodeRef(), m_strPath, m_request.getServletPath());
}
catch (FileNotFoundException e)
{
// The path is not valid - send a 404 error back to the client
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
}
// Set the response content type
m_response.setContentType(WebDAV.XML_CONTENT_TYPE);
// Create multistatus response
XMLWriter xml = createXMLWriter();
xml.startDocument();
String nsdec = generateNamespaceDeclarations(m_namespaces);
xml.startElement(
WebDAV.DAV_NS,
WebDAV.XML_MULTI_STATUS + nsdec,
WebDAV.XML_NS_MULTI_STATUS + nsdec,
getDAVHelper().getNullAttributes());
// Create the path for the current location in the tree
StringBuilder baseBuild = new StringBuilder(256);
baseBuild.append(getPath());
if (baseBuild.length() == 0 || baseBuild.charAt(baseBuild.length() - 1) != WebDAVHelper.PathSeperatorChar)
{
baseBuild.append(WebDAVHelper.PathSeperatorChar);
}
String basePath = baseBuild.toString();
// Output the response for the root node, depth zero
generateResponseForNode(xml, pathNodeInfo, basePath);
// If additional levels are required and the root node is a folder then recurse to the required
// level and output node details a level at a time
if (getDepth() != WebDAV.DEPTH_0 && pathNodeInfo.isFolder())
{
// Create the initial list of nodes to report
List<FileInfo> nodeInfos = new ArrayList<FileInfo>(10);
nodeInfos.add(pathNodeInfo);
int curDepth = WebDAV.DEPTH_1;
// Save the base path length
int baseLen = baseBuild.length();
// List of next level of nodes to report
List<FileInfo> nextNodeInfos = null;
if (getDepth() > WebDAV.DEPTH_1)
{
nextNodeInfos = new ArrayList<FileInfo>(10);
}
// Loop reporting each level of nodes to the requested depth
while (curDepth <= getDepth() && nodeInfos != null)
{
// Clear out the next level of nodes, if required
if (nextNodeInfos != null)
{
nextNodeInfos.clear();
}
// Output the current level of node(s), the node list should
// only contain folder nodes
for (FileInfo curNodeInfo : nodeInfos)
{
// Get the list of child nodes for the current node
List<FileInfo> childNodeInfos = fileFolderService.list(curNodeInfo.getNodeRef());
// can skip the current node if it doesn't have children
if (childNodeInfos.size() == 0)
{
continue;
}
// Output the child node details
// Generate the base path for the current parent node
baseBuild.setLength(baseLen);
try
{
String pathSnippet = getDAVHelper().getPathFromNode(pathNodeInfo.getNodeRef(), curNodeInfo.getNodeRef());
baseBuild.append(pathSnippet);
}
catch (FileNotFoundException e)
{
// move to the next node
continue;
}
int curBaseLen = baseBuild.length();
// Output the child node details
for (FileInfo curChildInfo : childNodeInfos)
{
// Build the path for the current child node
baseBuild.setLength(curBaseLen);
baseBuild.append(curChildInfo.getName());
// Output the current child node details
generateResponseForNode(xml, curChildInfo, baseBuild.toString());
// If the child is a folder add it to the list of next level nodes
if (nextNodeInfos != null && curChildInfo.isFolder())
{
nextNodeInfos.add(curChildInfo);
}
}
}
// Update the current tree depth
curDepth++;
// Move the next level of nodes to the current node list
nodeInfos = nextNodeInfos;
}
}
// Close the outer XML element
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_MULTI_STATUS, WebDAV.XML_NS_MULTI_STATUS);
// Send remaining data
xml.flush();
}
/**
* Creates a WebDAVProperty from the given XML node
*/
private WebDAVProperty createProperty(Node node)
{
WebDAVProperty property = null;
String strName = node.getLocalName();
String strNamespaceUri = node.getNamespaceURI();
if (strNamespaceUri.equals(WebDAV.DEFAULT_NAMESPACE_URI))
{
property = new WebDAVProperty(strName);
}
else
{
property = new WebDAVProperty(strName, strNamespaceUri, getNamespaceName(strNamespaceUri));
}
return property;
}
/**
* Retrieves the namespace name for the given namespace URI, one is
* generated if it doesn't exist
*/
private String getNamespaceName(String strNamespaceUri)
{
String strNamespaceName = m_namespaces.get(strNamespaceUri);
if (strNamespaceName == null)
{
strNamespaceName = "ns" + m_namespaces.size();
m_namespaces.put(strNamespaceUri, strNamespaceName);
}
return strNamespaceName;
}
/**
* Generates the required response XML for the current node
*
* @param xml XMLWriter
* @param node NodeRef
* @param path String
*/
private void generateResponseForNode(XMLWriter xml, FileInfo nodeInfo, String path) throws Exception
{
NodeRef nodeRef = nodeInfo.getNodeRef();
boolean isFolder = nodeInfo.isFolder();
// Output the response block for the current node
xml.startElement(
WebDAV.DAV_NS,
WebDAV.XML_RESPONSE,
WebDAV.XML_NS_RESPONSE,
getDAVHelper().getNullAttributes());
// Build the href string for the current node
String strHRef = WebDAV.getURLForPath(m_request, path, isFolder);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_HREF, WebDAV.XML_NS_HREF, getDAVHelper().getNullAttributes());
xml.write(strHRef);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_HREF, WebDAV.XML_NS_HREF);
switch (m_mode)
{
case GET_NAMED_PROPS:
generateNamedPropertiesResponse(xml, nodeInfo);
break;
case GET_ALL_PROPS:
generateAllPropertiesResponse(xml, nodeRef, isFolder);
break;
case FIND_PROPS:
generateFindPropertiesResponse(xml, nodeRef, isFolder);
break;
}
// Close off the response element
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_RESPONSE, WebDAV.XML_NS_RESPONSE);
}
/**
* Generates the XML response for a PROPFIND request that asks for a
* specific set of properties
*
* @param xml XMLWriter
* @param node NodeRef
* @param isDir boolean
*/
private void generateNamedPropertiesResponse(XMLWriter xml, FileInfo nodeInfo) throws Exception
{
NodeRef nodeRef = nodeInfo.getNodeRef();
boolean isFolder = nodeInfo.isFolder();
// Get the properties for the node
Map<QName, Serializable> props = getNodeService().getProperties(nodeRef);
// Output the start of the properties element
Attributes nullAttr = getDAVHelper().getNullAttributes();
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT, nullAttr);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP, nullAttr);
ArrayList<WebDAVProperty> propertiesNotFound = new ArrayList<WebDAVProperty>();
TypeConverter typeConv = DefaultTypeConverter.INSTANCE;
// Loop through the requested property list
for (WebDAVProperty property : m_properties)
{
// Get the requested property details
String propName = property.getName();
String propNamespaceUri = property.getNamespaceUri();
// String propNamespaceName = property.getNamespaceName();
// Check if the property is a standard WebDAV property
Object davValue = null;
if (propNamespaceUri.equals(WebDAV.DEFAULT_NAMESPACE_URI))
{
// Check if the client is requesting lock information
if (propName.equals(WebDAV.XML_LOCK_DISCOVERY)) // && metaData.isLocked())
{
generateLockDiscoveryResponse(xml, nodeRef, isFolder);
}
else if (propName.equals(WebDAV.XML_SUPPORTED_LOCK))
{
// Output the supported lock types
writeLockTypes(xml);
}
// Check if the client is requesting the resource type
else if (propName.equals(WebDAV.XML_RESOURCE_TYPE))
{
// If the node is a folder then return as a collection type
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_RESOURCE_TYPE, WebDAV.XML_NS_RESOURCE_TYPE, nullAttr);
if (isFolder)
{
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_COLLECTION));
}
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_RESOURCE_TYPE, WebDAV.XML_NS_RESOURCE_TYPE);
}
else if (propName.equals(WebDAV.XML_DISPLAYNAME))
{
// Get the node name
if (getRootNodeRef().equals(nodeRef))
{
// Output an empty name for the root node
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_SOURCE));
}
else
{
// Get the node name
davValue = WebDAV.getDAVPropertyValue(props, WebDAV.XML_DISPLAYNAME);
// Output the node name
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_DISPLAYNAME, WebDAV.XML_NS_DISPLAYNAME, nullAttr);
if (davValue != null)
{
String name = typeConv.convert(String.class, davValue);
if (name == null || name.length() == 0)
{
logger.error("WebDAV name is null, value=" + davValue.getClass().getName() + ", node=" + nodeRef);
}
xml.write(name);
}
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_DISPLAYNAME, WebDAV.XML_NS_DISPLAYNAME);
}
}
else if (propName.equals(WebDAV.XML_SOURCE))
{
// NOTE: source is always a no content element in our
// implementation
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_SOURCE));
}
else if (propName.equals(WebDAV.XML_GET_LAST_MODIFIED))
{
// Get the modifed date/time
davValue = WebDAV.getDAVPropertyValue(props, WebDAV.XML_GET_LAST_MODIFIED);
// Output the last modified date of the node
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_LAST_MODIFIED, WebDAV.XML_NS_GET_LAST_MODIFIED,
nullAttr);
if (davValue != null)
xml.write(WebDAV.formatModifiedDate(typeConv.convert(Date.class, davValue)));
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_LAST_MODIFIED, WebDAV.XML_NS_GET_LAST_MODIFIED);
}
else if (propName.equals(WebDAV.XML_GET_CONTENT_LANGUAGE) && !isFolder)
{
// Get the content language
// TODO:
// Output the content language
xml.startElement(
WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_LANGUAGE,
WebDAV.XML_NS_GET_CONTENT_LANGUAGE, nullAttr);
// TODO:
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_LANGUAGE, WebDAV.XML_NS_GET_CONTENT_LANGUAGE);
}
else if (propName.equals(WebDAV.XML_GET_CONTENT_TYPE) && !isFolder)
{
// Get the content type
davValue = WebDAV.getDAVPropertyValue(props, WebDAV.XML_GET_CONTENT_TYPE);
// Output the content type
xml.startElement(
WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_TYPE,
WebDAV.XML_NS_GET_CONTENT_TYPE, nullAttr);
if (davValue != null)
xml.write(typeConv.convert(String.class, davValue));
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_TYPE, WebDAV.XML_NS_GET_CONTENT_TYPE);
}
else if (propName.equals(WebDAV.XML_GET_ETAG) && !isFolder)
{
// Output the etag
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_ETAG, WebDAV.XML_NS_GET_ETAG, nullAttr);
xml.write(getDAVHelper().makeETag(nodeRef));
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_ETAG, WebDAV.XML_NS_GET_ETAG);
}
else if (propName.equals(WebDAV.XML_GET_CONTENT_LENGTH))
{
// Get the content length, if it's not a folder
long len = 0;
if (!isFolder)
{
ContentData contentData = (ContentData) props.get(ContentModel.PROP_CONTENT);
if (contentData != null)
len = contentData.getSize();
}
// Output the content length
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_LENGTH, WebDAV.XML_NS_GET_CONTENT_LENGTH,
nullAttr);
xml.write("" + len);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_LENGTH, WebDAV.XML_NS_GET_CONTENT_LENGTH);
}
else if (propName.equals(WebDAV.XML_CREATION_DATE))
{
// Get the creation date
davValue = WebDAV.getDAVPropertyValue(props, WebDAV.XML_CREATION_DATE);
// Output the creation date
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_CREATION_DATE, WebDAV.XML_NS_CREATION_DATE, nullAttr);
if (davValue != null)
xml.write(WebDAV.formatCreationDate(typeConv.convert(Date.class, davValue)));
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_CREATION_DATE, WebDAV.XML_NS_CREATION_DATE);
}
else
{
// Could not map the requested property to an Alfresco property
if (property.getName().equals(WebDAV.XML_HREF) == false)
propertiesNotFound.add(property);
}
}
else
{
// Look in the custom properties
// TODO: Custom properties lookup
// String qualifiedName = propNamespaceUri + WebDAV.NAMESPACE_SEPARATOR + propName;
propertiesNotFound.add(property);
}
}
// Close off the successful part of the response
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS, nullAttr);
xml.write(WebDAV.HTTP1_1 + " " + HttpServletResponse.SC_OK + " " + WebDAV.SC_OK_DESC);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT);
// If some of the requested properties were not found return another
// status section
if (propertiesNotFound.size() > 0)
{
// Start the second status section
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT, nullAttr);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP, nullAttr);
// Loop through the list of properties that were not found
for (WebDAVProperty property : propertiesNotFound)
{
// Output the property not found status block
String propName = property.getName();
String propNamespaceName = property.getNamespaceName();
String propQName = propName;
if (propNamespaceName != null && propNamespaceName.length() > 0)
propQName = propNamespaceName + ":" + propName;
xml.write(DocumentHelper.createElement(propQName));
}
// Close the unsuccessful part of the response
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS, nullAttr);
xml.write(WebDAV.HTTP1_1 + " " + HttpServletResponse.SC_NOT_FOUND + " " + WebDAV.SC_NOT_FOUND_DESC);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT);
}
}
/**
* Generates the XML response for a PROPFIND request that asks for all known
* properties
*
* @param xml XMLWriter
* @param node NodeRef
* @param isDir boolean
*/
private void generateAllPropertiesResponse(XMLWriter xml, NodeRef node, boolean isDir) throws Exception
{
// Get the properties for the node
Map<QName, Serializable> props = getNodeService().getProperties(node);
// Output the start of the properties element
Attributes nullAttr = getDAVHelper().getNullAttributes();
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT, nullAttr);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP, nullAttr);
// Generate a lock status report, if locked
generateLockDiscoveryResponse(xml, node, isDir);
// Output the supported lock types
writeLockTypes(xml);
// If the node is a folder then return as a collection type
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_RESOURCE_TYPE, WebDAV.XML_NS_RESOURCE_TYPE, nullAttr);
if (isDir)
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_COLLECTION));
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_RESOURCE_TYPE, WebDAV.XML_NS_RESOURCE_TYPE);
// Get the node name
Object davValue = WebDAV.getDAVPropertyValue(props, WebDAV.XML_DISPLAYNAME);
TypeConverter typeConv = DefaultTypeConverter.INSTANCE;
// Output the node name
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_DISPLAYNAME, WebDAV.XML_NS_DISPLAYNAME, nullAttr);
if (davValue != null)
{
String name = typeConv.convert(String.class, davValue);
if (name == null || name.length() == 0)
{
logger.error("WebDAV name is null, value=" + davValue.getClass().getName() + ", node=" + node);
}
xml.write(name);
}
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_DISPLAYNAME, WebDAV.XML_NS_DISPLAYNAME);
// Output the source
//
// NOTE: source is always a no content element in our implementation
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_SOURCE));
// Get the creation date
davValue = WebDAV.getDAVPropertyValue(props, WebDAV.XML_CREATION_DATE);
// Output the creation date
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_CREATION_DATE, WebDAV.XML_NS_CREATION_DATE, nullAttr);
if (davValue != null)
xml.write(WebDAV.formatCreationDate(typeConv.convert(Date.class, davValue)));
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_CREATION_DATE, WebDAV.XML_NS_CREATION_DATE);
// Get the modifed date/time
davValue = WebDAV.getDAVPropertyValue(props, WebDAV.XML_GET_LAST_MODIFIED);
// Output the last modified date of the node
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_LAST_MODIFIED, WebDAV.XML_NS_GET_LAST_MODIFIED, nullAttr);
if (davValue != null)
xml.write(WebDAV.formatModifiedDate(typeConv.convert(Date.class, davValue)));
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_LAST_MODIFIED, WebDAV.XML_NS_GET_LAST_MODIFIED);
// For a file node output the content language and content type
if (isDir == false)
{
// Get the content language
// TODO:
// Output the content language
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_LANGUAGE, WebDAV.XML_NS_GET_CONTENT_LANGUAGE,
nullAttr);
// TODO:
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_LANGUAGE, WebDAV.XML_NS_GET_CONTENT_LANGUAGE);
// Get the content type
davValue = WebDAV.getDAVPropertyValue(props, WebDAV.XML_GET_CONTENT_TYPE);
// Output the content type
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_TYPE, WebDAV.XML_NS_GET_CONTENT_TYPE, nullAttr);
if (davValue != null)
xml.write(typeConv.convert(String.class, davValue));
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_TYPE, WebDAV.XML_NS_GET_CONTENT_TYPE);
// Output the etag
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_ETAG, WebDAV.XML_NS_GET_ETAG, nullAttr);
xml.write(getDAVHelper().makeETag(node));
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_ETAG, WebDAV.XML_NS_GET_ETAG);
}
// Get the content length, if it's not a folder
long len = 0;
if (isDir == false)
{
ContentData contentData = (ContentData) props.get(ContentModel.PROP_CONTENT);
if (contentData != null)
len = contentData.getSize();
}
// Output the content length
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_LENGTH, WebDAV.XML_NS_GET_CONTENT_LENGTH, nullAttr);
xml.write("" + len);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_GET_CONTENT_LENGTH, WebDAV.XML_NS_GET_CONTENT_LENGTH);
// Print out all the custom properties
// TODO: Output custom properties
// Close off the response
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS, nullAttr);
xml.write(WebDAV.HTTP1_1 + " " + HttpServletResponse.SC_OK + " " + WebDAV.SC_OK_DESC);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT);
}
/**
* Generates the XML response for a PROPFIND request that asks for a list of
* all known properties
*
* @param xml XMLWriter
* @param node NodeRef
* @param isDir boolean
*/
private void generateFindPropertiesResponse(XMLWriter xml, NodeRef node, boolean isDir)
{
try
{
// Output the start of the properties element
Attributes nullAttr = getDAVHelper().getNullAttributes();
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT, nullAttr);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP, nullAttr);
// Output the well-known properties
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_LOCK_DISCOVERY));
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_SUPPORTED_LOCK));
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_RESOURCE_TYPE));
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_DISPLAYNAME));
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_GET_LAST_MODIFIED));
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_GET_CONTENT_LENGTH));
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_CREATION_DATE));
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_GET_ETAG));
if (isDir)
{
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_GET_CONTENT_LANGUAGE));
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_GET_CONTENT_TYPE));
}
// Output the custom properties
// TODO: Custom properties
// Close off the response
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROP, WebDAV.XML_NS_PROP);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS, nullAttr);
xml.write(WebDAV.HTTP1_1 + " " + HttpServletResponse.SC_OK + " " + WebDAV.SC_OK_DESC);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_STATUS, WebDAV.XML_NS_STATUS);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_PROPSTAT, WebDAV.XML_NS_PROPSTAT);
}
catch (Exception ex)
{
// Convert to a runtime exception
throw new AlfrescoRuntimeException("XML processing error", ex);
}
}
/**
* Generates the XML response snippet showing the lock information for the
* given path
*
* @param xml XMLWriter
* @param node NodeRef
* @param isDir boolean
*/
private void generateLockDiscoveryResponse(XMLWriter xml, NodeRef node, boolean isDir) throws Exception
{
// Get the lock status for the node
LockService lockService = getLockService();
LockStatus lockSts = lockService.getLockStatus(node);
// Output the lock status reponse
if (lockSts != LockStatus.NO_LOCK)
generateLockDiscoveryXML(xml, node);
}
/**
* Output the supported lock types XML element
*
* @param xml XMLWriter
*/
private void writeLockTypes(XMLWriter xml)
{
try
{
AttributesImpl nullAttr = getDAVHelper().getNullAttributes();
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_SUPPORTED_LOCK, WebDAV.XML_NS_SUPPORTED_LOCK, nullAttr);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE, nullAttr);
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_EXCLUSIVE));
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_NS_LOCK_TYPE, nullAttr);
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_WRITE));
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_NS_LOCK_TYPE);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_SUPPORTED_LOCK, WebDAV.XML_NS_SUPPORTED_LOCK);
}
catch (Exception ex)
{
throw new AlfrescoRuntimeException("XML write error", ex);
}
}
}

View File

@@ -0,0 +1,158 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
import java.io.InputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
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.ContentWriter;
import org.alfresco.service.namespace.QName;
/**
* Implements the WebDAV PUT method
*
* @author Gavin Cornwell
*/
public class PutMethod extends WebDAVMethod
{
// Request parameters
private String m_strLockToken = null;
private String m_strContentType = null;
private boolean m_expectHeaderPresent = false;
/**
* Default constructor
*/
public PutMethod()
{
}
/**
* Parse the request headers
*
* @exception WebDAVServerException
*/
protected void parseRequestHeaders() throws WebDAVServerException
{
m_strContentType = m_request.getHeader(WebDAV.HEADER_CONTENT_TYPE);
String strExpect = m_request.getHeader(WebDAV.HEADER_EXPECT);
if (strExpect != null && strExpect.equals(WebDAV.HEADER_EXPECT_CONTENT))
{
m_expectHeaderPresent = true;
}
// Get the lock token, if any
m_strLockToken = parseIfHeader();
}
/**
* Parse the request body
*
* @exception WebDAVServerException
*/
protected void parseRequestBody() throws WebDAVServerException
{
// Nothing to do in this method, the body contains
// the content it will be dealt with later
}
/**
* Exceute the WebDAV request
*
* @exception WebDAVServerException
*/
protected void executeImpl() throws WebDAVServerException, Exception
{
FileFolderService fileFolderService = getFileFolderService();
// Get the status for the request path
FileInfo contentNodeInfo = null;
boolean created = false;
try
{
contentNodeInfo = getDAVHelper().getNodeForPath(getRootNodeRef(), getPath(), getServletPath());
// make sure that we are not trying to use a folder
if (contentNodeInfo.isFolder())
{
throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST);
}
}
catch (FileNotFoundException e)
{
// the file doesn't exist - create it
String[] paths = getDAVHelper().splitPath(getPath());
try
{
FileInfo parentNodeInfo = getDAVHelper().getNodeForPath(getRootNodeRef(), paths[0], getServletPath());
// create file
contentNodeInfo = fileFolderService.create(parentNodeInfo.getNodeRef(), paths[1], ContentModel.TYPE_CONTENT);
created = true;
// apply the titled aspect - title and description
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(3, 1.0f);
titledProps.put(ContentModel.PROP_TITLE, paths[1]);
titledProps.put(ContentModel.PROP_DESCRIPTION, "");
getNodeService().addAspect(contentNodeInfo.getNodeRef(), ContentModel.ASPECT_TITLED, titledProps);
}
catch (FileNotFoundException ee)
{
// bad path
throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST);
}
catch (FileExistsException ee)
{
// bad path
throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST);
}
}
// Access the content
ContentWriter writer = fileFolderService.getWriter(contentNodeInfo.getNodeRef());
// set content properties
if (m_strContentType != null)
{
writer.setMimetype(m_strContentType);
}
else
{
String guessedMimetype = getServiceRegistry().getMimetypeService().guessMimetype(contentNodeInfo.getName());
writer.setMimetype(guessedMimetype);
}
// use default encoding
writer.setEncoding("UTF-8");
// Get the input stream from the request data
InputStream input = m_request.getInputStream();
// Write the new data to the content node
writer.putContent(input);
// Set the response status, depending if the node existed or not
m_response.setStatus(created ? HttpServletResponse.SC_CREATED : HttpServletResponse.SC_NO_CONTENT);
}
}

View File

@@ -0,0 +1,176 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.lock.LockStatus;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
/**
* Implements the WebDAV UNLOCK method
*
* @author gavinc
*/
public class UnlockMethod extends WebDAVMethod
{
private String m_strLockToken = null;
/**
* Default constructor
*/
public UnlockMethod()
{
}
/**
* Return the lock token of an existing lock
*
* @return String
*/
protected final String getLockToken()
{
return m_strLockToken;
}
/**
* Parse the request headers
*
* @exception WebDAVServerException
*/
protected void parseRequestHeaders() throws WebDAVServerException
{
// Get the lock token, if any
String strLockTokenHeader = m_request.getHeader(WebDAV.HEADER_LOCK_TOKEN);
// DEBUG
if (logger.isDebugEnabled())
logger.debug("Parsing Lock-Token header: " + strLockTokenHeader);
// Validate the lock token
if (strLockTokenHeader != null && strLockTokenHeader.startsWith("<") && strLockTokenHeader.endsWith(">"))
{
try
{
m_strLockToken = strLockTokenHeader.substring(
WebDAV.OPAQUE_LOCK_TOKEN.length() + 1,
strLockTokenHeader.length() - 1);
}
catch (IndexOutOfBoundsException e)
{
logger.warn("Failed to parse If header: " + strLockTokenHeader);
}
}
// If there is no token this is a bad request so send an error back
if (m_strLockToken == null)
{
throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST);
}
}
/**
* Parse the request body
*
* @exception WebDAVServerException
*/
protected void parseRequestBody() throws WebDAVServerException
{
// Nothing to do in this method
}
/**
* Exceute the request
*
* @exception WebDAVServerException
*/
protected void executeImpl() throws WebDAVServerException
{
if (logger.isDebugEnabled())
{
logger.debug("Lock node; path=" + getPath() + ", token=" + getLockToken());
}
FileInfo lockNodeInfo = null;
try
{
lockNodeInfo = getDAVHelper().getNodeForPath(getRootNodeRef(), getPath(), getServletPath());
}
catch (FileNotFoundException e)
{
throw new WebDAVServerException(HttpServletResponse.SC_NOT_FOUND);
}
// Parse the lock token
String[] lockInfo = WebDAV.parseLockToken(getLockToken());
if (lockInfo == null)
{
// Bad lock token
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
}
// Get the lock status for the node
LockService lockService = getDAVHelper().getLockService();
// String nodeId = lockInfo[0];
// String userName = lockInfo[1];
LockStatus lockSts = lockService.getLockStatus(lockNodeInfo.getNodeRef());
if (lockSts == LockStatus.LOCK_OWNER)
{
// Unlock the node
lockService.unlock(lockNodeInfo.getNodeRef());
// Indicate that the unlock was successful
m_response.setStatus(HttpServletResponse.SC_NO_CONTENT);
// DEBUG
if (logger.isDebugEnabled())
{
logger.debug("Unlock token=" + getLockToken() + " Successful");
}
}
else if (lockSts == LockStatus.NO_LOCK)
{
// DEBUG
if (logger.isDebugEnabled())
logger.debug("Unlock token=" + getLockToken() + " Not locked");
// Node is not locked
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
}
else if (lockSts == LockStatus.LOCKED)
{
// DEBUG
if (logger.isDebugEnabled())
logger.debug("Unlock token=" + getLockToken() + " Not lock owner");
// Node is locked but not by this user
throw new WebDAVServerException(HttpServletResponse.SC_PRECONDITION_FAILED);
}
else if (lockSts == LockStatus.LOCK_EXPIRED)
{
// DEBUG
if (logger.isDebugEnabled())
logger.debug("Unlock token=" + getLockToken() + " Lock expired");
// Return a success status
m_response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
}
}

View File

@@ -0,0 +1,552 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
import java.io.Serializable;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Helper class used by the WebDAV protocol handling classes
*
* @author gavinc
*/
public class WebDAV
{
// Logging
private static Log logger = LogFactory.getLog("org.alfresco.protocol.webdav");
// WebDAV XML namespace
public static final String DAV_NS = "D";
public static final String DAV_NS_PREFIX = DAV_NS + ":";
// PROPFIND depth
public static final int DEPTH_0 = 0;
public static final int DEPTH_1 = 1;
public static final int DEPTH_INFINITY = -1;
public static final short TIMEOUT_INFINITY = -1;
// WebDAV HTTP response codes
public static final int WEBDAV_SC_MULTI_STATUS = 207;
public static final int WEBDAV_SC_LOCKED = 423;
// HTTP response code descriptions
public static final String SC_OK_DESC = "OK";
public static final String SC_NOT_FOUND_DESC = "Not Found";
// HTTP methods
public static final String METHOD_PUT = "PUT";
public static final String METHOD_POST = "POST";
public static final String METHOD_GET = "GET";
public static final String METHOD_DELETE = "DELETE";
public static final String METHOD_HEAD = "HEAD";
public static final String METHOD_OPTIONS = "OPTIONS";
public static final String METHOD_PROPFIND = "PROPFIND";
public static final String METHOD_PROPPATCH = "PROPPATCH";
public static final String METHOD_MKCOL = "MKCOL";
public static final String METHOD_MOVE = "MOVE";
public static final String METHOD_COPY = "COPY";
public static final String METHOD_LOCK = "LOCK";
public static final String METHOD_UNLOCK = "UNLOCK";
// HTTP headers
public static final String HEADER_CONTENT_LENGTH = "Content-Length";
public static final String HEADER_CONTENT_TYPE = "Content-Type";
public static final String HEADER_DEPTH = "Depth";
public static final String HEADER_DESTINATION = "Destination";
public static final String HEADER_ETAG = "ETag";
public static final String HEADER_EXPECT = "Expect";
public static final String HEADER_EXPECT_CONTENT = "100-continue";
public static final String HEADER_IF = "If";
public static final String HEADER_IF_MATCH = "If-Match";
public static final String HEADER_IF_MODIFIED_SINCE = "If-Modified-Since";
public static final String HEADER_IF_NONE_MATCH = "If-None-Match";
public static final String HEADER_IF_RANGE = "If-Range";
public static final String HEADER_IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
public static final String HEADER_LAST_MODIFIED = "Last-Modified";
public static final String HEADER_LOCK_TOKEN = "Lock-Token";
public static final String HEADER_OVERWRITE = "Overwrite";
public static final String HEADER_RANGE = "Range";
public static final String HEADER_TIMEOUT = "Timeout";
// If-Modified/If-Unmodified date format
public static final String HEADER_IF_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz";
// General string constants
public static final String ASTERISK = "*";
public static final String DEFAULT_NAMESPACE_URI = "DAV:";
public static final String DIR_SEPARATOR = "/";
public static final String FAKE_TOKEN = "faketoken";
public static final String HTTP1_1 = "HTTP/1.1";
public static final String INFINITE = "Infinite";
public static final String INFINITY = "infinity";
public static final String OPAQUE_LOCK_TOKEN = "opaquelocktoken:";
public static final String NAMESPACE_SEPARATOR = ":";
public static final String SECOND = "Second-";
public static final String HEADER_VALUE_SEPARATOR = ",";
public static final String ZERO = "0";
public static final String ONE = "1";
public static final String T = "T";
// Strings used in WebDAV XML payload
public static final String XML_NS = "xmlns";
public static final String XML_ACTIVE_LOCK = "activelock";
public static final String XML_ALLPROP = "allprop";
public static final String XML_COLLECTION = "collection";
public static final String XML_CREATION_DATE = "creationdate";
public static final String XML_DEPTH = "depth";
public static final String XML_DISPLAYNAME = "displayname";
public static final String XML_EXCLUSIVE = "exclusive";
public static final String XML_GET_CONTENT_LANGUAGE = "getcontentlanguage";
public static final String XML_GET_CONTENT_LENGTH = "getcontentlength";
public static final String XML_GET_CONTENT_TYPE = "getcontenttype";
public static final String XML_GET_ETAG = "getetag";
public static final String XML_GET_LAST_MODIFIED = "getlastmodified";
public static final String XML_HREF = "href";
public static final String XML_LOCK_DISCOVERY = "lockdiscovery";
public static final String XML_LOCK_SCOPE = "lockscope";
public static final String XML_LOCK_TOKEN = "locktoken";
public static final String XML_LOCK_TYPE = "locktype";
public static final String XML_MULTI_STATUS = "multistatus";
public static final String XML_OWNER = "owner";
public static final String XML_PROP = "prop";
public static final String XML_PROPNAME = "propname";
public static final String XML_PROPSTAT = "propstat";
public static final String XML_RESOURCE_TYPE = "resourcetype";
public static final String XML_RESPONSE = "response";
public static final String XML_SHARED = "shared";
public static final String XML_SOURCE = "source";
public static final String XML_STATUS = "status";
public static final String XML_SUPPORTED_LOCK = "supportedlock";
public static final String XML_TIMEOUT = "timeout";
public static final String XML_WRITE = "write";
// Namespaced versions of payload elements
public static final String XML_NS_ACTIVE_LOCK = DAV_NS_PREFIX + "activelock";
public static final String XML_NS_ALLPROP = DAV_NS_PREFIX + "allprop";
public static final String XML_NS_COLLECTION = DAV_NS_PREFIX + "collection";
public static final String XML_NS_CREATION_DATE = DAV_NS_PREFIX + "creationdate";
public static final String XML_NS_DEPTH = DAV_NS_PREFIX + "depth";
public static final String XML_NS_DISPLAYNAME = DAV_NS_PREFIX + "displayname";
public static final String XML_NS_EXCLUSIVE = DAV_NS_PREFIX + "exclusive";
public static final String XML_NS_GET_CONTENT_LANGUAGE = DAV_NS_PREFIX + "getcontentlanguage";
public static final String XML_NS_GET_CONTENT_LENGTH = DAV_NS_PREFIX + "getcontentlength";
public static final String XML_NS_GET_CONTENT_TYPE = DAV_NS_PREFIX + "getcontenttype";
public static final String XML_NS_GET_ETAG = DAV_NS_PREFIX + "getetag";
public static final String XML_NS_GET_LAST_MODIFIED = DAV_NS_PREFIX + "getlastmodified";
public static final String XML_NS_HREF = DAV_NS_PREFIX + "href";
public static final String XML_NS_LOCK_DISCOVERY = DAV_NS_PREFIX + "lockdiscovery";
public static final String XML_NS_LOCK_SCOPE = DAV_NS_PREFIX + "lockscope";
public static final String XML_NS_LOCK_TOKEN = DAV_NS_PREFIX + "locktoken";
public static final String XML_NS_LOCK_TYPE = DAV_NS_PREFIX + "locktype";
public static final String XML_NS_MULTI_STATUS = DAV_NS_PREFIX + "multistatus";
public static final String XML_NS_OWNER = DAV_NS_PREFIX + "owner";
public static final String XML_NS_PROP = DAV_NS_PREFIX + "prop";
public static final String XML_NS_PROPNAME = DAV_NS_PREFIX + "propname";
public static final String XML_NS_PROPSTAT = DAV_NS_PREFIX + "propstat";
public static final String XML_NS_RESOURCE_TYPE = DAV_NS_PREFIX + "resourcetype";
public static final String XML_NS_RESPONSE = DAV_NS_PREFIX + "response";
public static final String XML_NS_SHARED = DAV_NS_PREFIX + "shared";
public static final String XML_NS_SOURCE = DAV_NS_PREFIX + "source";
public static final String XML_NS_STATUS = DAV_NS_PREFIX + "status";
public static final String XML_NS_SUPPORTED_LOCK = DAV_NS_PREFIX + "supportedlock";
public static final String XML_NS_TIMEOUT = DAV_NS_PREFIX + "timeout";
public static final String XML_NS_WRITE = DAV_NS_PREFIX + "write";
public static final String XML_CONTENT_TYPE = "text/xml; charset=UTF-8";
private static HashMap s_codeDescriptions = null;
// Path seperator
private static final String DIR_SEPERATOR = "\\";
// Path seperator
public static final String PathSeperator = "/";
public static final char PathSeperatorChar = '/';
// Lock token seperator
public static final String LOCK_TOKEN_SEPERATOR = ":";
// Root path
private static final String RootPath = PathSeperator;
// Map WebDAV property names to Alfresco property names
private static Hashtable<String, QName> _propertyNameMap;
// WebDAV creation date/time formatter
private static SimpleDateFormat _creationDateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
// HTTP header date/time formatter
private static SimpleDateFormat _httpDateFormatter = new SimpleDateFormat(HEADER_IF_DATE_FORMAT);
/**
* Formats the given date so that it conforms with the Last-Modified HTTP header
*
* @param date The date to format
* @return The formatted date string
*/
public static String formatModifiedDate(Date date)
{
return _httpDateFormatter.format(date);
}
/**
* Formats the given date so that it conforms with the Last-Modified HTTP header
*
* @param date long
* @return The formatted date string
*/
public static String formatModifiedDate(long ldate)
{
return _httpDateFormatter.format(new Date(ldate));
}
/**
* Formats the given date so that it conforms with the WebDAV creation date/time format
*
* @param date The date to format
* @return The formatted date string
*/
public static String formatCreationDate(Date date)
{
return _creationDateFormatter.format(date);
}
/**
* Formats the given date so that it conforms with the WebDAV creation date/time format
*
* @param date long
* @return The formatted date string
*/
public static String formatCreationDate(long ldate)
{
return _creationDateFormatter.format(new Date(ldate));
}
/**
* Formats the given date for use in the HTTP header
*
* @param date Date
* @return String
*/
public static String formatHeaderDate(Date date)
{
return _httpDateFormatter.format( date);
}
/**
* Formats the given date for use in the HTTP header
*
* @param date long
* @return String
*/
public static String formatHeaderDate(long date)
{
return _httpDateFormatter.format( new Date(date));
}
/**
* Return the Alfresco property value for the specified WebDAV property
*
* @param props Map<QName, Serializable>
* @param davPropName String
* @return Object
*/
public static Object getDAVPropertyValue( Map<QName, Serializable> props, String davPropName)
{
// Convert the WebDAV property name to the corresponding Alfresco property
QName propName = _propertyNameMap.get( davPropName);
if ( propName == null)
throw new AlfrescoRuntimeException("No mapping for WebDAV property " + davPropName);
// Return the property value
Object value = props.get(propName);
if (value instanceof ContentData)
{
ContentData contentData = (ContentData) value;
if (davPropName.equals(WebDAV.XML_GET_CONTENT_TYPE))
{
value = contentData.getMimetype();
}
else if (davPropName.equals(WebDAV.XML_GET_CONTENT_LENGTH))
{
value = new Long(contentData.getSize());
}
}
return value;
}
/**
* Maps the current HTTP request to a path that can be used to access a content repository
*
* @param request HTTP request
* @return A content repository path
*/
public static String getRepositoryPath(HttpServletRequest request)
{
// Try and get the path
String strPath = request.getPathInfo();
// If we failed to get the path from the request try and get the path from the servlet path
if (strPath == null)
{
strPath = request.getServletPath();
}
// If we still have not got a path then default to the root directory
if (strPath == null || strPath.length() == 0)
{
strPath = RootPath;
}
// Make sure there are no trailing slashes
else if (strPath.endsWith(DIR_SEPARATOR))
{
strPath = strPath.substring(0, strPath.length() - 1);
}
// Check if the path starts with the base servlet path
if ( strPath.startsWith(request.getServletPath()))
{
int len = request.getServletPath().length();
if ( strPath.length() > len)
strPath = strPath.substring(len);
else
strPath = RootPath;
}
// Return the path
return decodeURL(strPath);
}
/**
* Returns a URL that could be used to access the given path.
*
* @param request HttpServletRequest
* @param path String
* @param isCollection boolean
* @return String
*/
public static String getURLForPath(HttpServletRequest request, String path, boolean isCollection)
{
StringBuilder urlStr = new StringBuilder(request.getRequestURI());
String servletPath = request.getServletPath();
int rootPos = urlStr.indexOf(servletPath);
if ( rootPos != -1)
urlStr.setLength(rootPos + servletPath.length());
if ( urlStr.charAt(urlStr.length() - 1) != PathSeperatorChar)
urlStr.append(PathSeperator);
if ( path.equals(RootPath) == false)
{
if ( path.startsWith(PathSeperator))
urlStr.append(path.substring(1));
else
urlStr.append(path);
}
return urlStr.toString();
}
/**
* Returns a context-relative path, beginning with a "/", that represents the canonical version
* of the specified path after ".." and "." elements are resolved out. If the specified path
* attempts to go outside the boundaries of the current context (i.e. too many ".." path
* elements are present), return <code>null</code> instead.
*
* @param strPath The path to be decoded
*/
public static String decodeURL(String strPath)
{
if (strPath == null)
return null;
// Resolve encoded characters in the normalized path, which also handles encoded
// spaces so we can skip that later. Placed at the beginning of the chain so that
// encoded bad stuff(tm) can be caught by the later checks
String strNormalized = null;
try
{
strNormalized = URLDecoder.decode(strPath, "UTF-8");
}
catch (Exception ex)
{
logger.error("Error in decodeURL, URL = " + strPath, ex);
}
if (strNormalized == null)
return (null);
// Normalize the slashes and add leading slash if necessary
if (strNormalized.indexOf('\\') >= 0)
strNormalized = strNormalized.replace('\\', '/');
if (!strNormalized.startsWith("/"))
strNormalized = "/" + strNormalized;
// Resolve occurrences of "//" in the normalized path
while (true)
{
int index = strNormalized.indexOf("//");
if (index < 0)
break;
strNormalized = strNormalized.substring(0, index) + strNormalized.substring(index + 1);
}
// Resolve occurrences of "/./" in the normalized path
while (true)
{
int index = strNormalized.indexOf("/./");
if (index < 0)
break;
strNormalized = strNormalized.substring(0, index) + strNormalized.substring(index + 2);
}
// Resolve occurrences of "/../" in the normalized path
while (true)
{
int index = strNormalized.indexOf("/../");
if (index < 0)
break;
if (index == 0)
return (null); // Trying to go outside our context
int index2 = strNormalized.lastIndexOf('/', index - 1);
strNormalized = strNormalized.substring(0, index2) + strNormalized.substring(index + 3);
}
// Return the normalized path that we have completed
return strNormalized;
}
/**
* Make a unique lock token
*
* @param lockNode NodeRef
* @param owner String
* @return String
*/
public static final String makeLockToken(NodeRef lockNode, String owner)
{
StringBuilder str = new StringBuilder();
str.append(WebDAV.OPAQUE_LOCK_TOKEN);
str.append(lockNode.getId());
str.append(LOCK_TOKEN_SEPERATOR);
str.append(owner);
return str.toString();
}
/**
* Parse a lock token returning the node if and username
*
* @param lockToken String
* @return String[]
*/
public static final String[] parseLockToken(String lockToken)
{
// Check if the lock token is valid
if ( lockToken == null)
return null;
// Check if the token contains the lock token header
if ( lockToken.startsWith(WebDAV.OPAQUE_LOCK_TOKEN))
lockToken = lockToken.substring(WebDAV.OPAQUE_LOCK_TOKEN.length());
// Split the node id and username tokens
int pos = lockToken.indexOf(LOCK_TOKEN_SEPERATOR);
if ( pos == -1)
return null;
String[] tokens = new String[2];
tokens[0] = lockToken.substring(0,pos);
tokens[1] = lockToken.substring(pos + 1);
return tokens;
}
/**
* Static initializer
*/
static
{
// Create the WebDAV to Alfresco property mapping table
_propertyNameMap = new Hashtable<String, QName>();
_propertyNameMap.put(XML_DISPLAYNAME, ContentModel.PROP_NAME);
_propertyNameMap.put(XML_CREATION_DATE, ContentModel.PROP_CREATED);
_propertyNameMap.put(XML_GET_LAST_MODIFIED, ContentModel.PROP_MODIFIED);
_propertyNameMap.put(XML_GET_CONTENT_TYPE, ContentModel.PROP_CONTENT);
}
}

View File

@@ -0,0 +1,418 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
import org.alfresco.model.ContentModel;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.lock.LockService;
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.CopyService;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.util.EqualsHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.helpers.AttributesImpl;
/**
* WebDAV Protocol Helper Class
*
* <p>Provides helper methods for repository access using the WebDAV protocol.
*
* @author GKSpencer
*/
public class WebDAVHelper
{
// Constants
// Path seperator
public static final String PathSeperator = "/";
public static final char PathSeperatorChar = '/';
// Logging
private static Log logger = LogFactory.getLog("org.alfresco.protocol.webdav");
// Service registry
private ServiceRegistry m_serviceRegistry;
// Services
private NodeService m_nodeService;
private FileFolderService m_fileFolderService;
private SearchService m_searchService;
private NamespaceService m_namespaceService;
private DictionaryService m_dictionaryService;
private MimetypeService m_mimetypeService;
private LockService m_lockService;
private AuthenticationService m_authService;
// Empty XML attribute list
private AttributesImpl m_nullAttribs = new AttributesImpl();
/**
* Class constructor
*
* @param serviceRegistry ServiceRegistry
* @param authService AuthenticationService
*/
protected WebDAVHelper(ServiceRegistry serviceRegistry, AuthenticationService authService)
{
m_serviceRegistry = serviceRegistry;
m_nodeService = m_serviceRegistry.getNodeService();
m_fileFolderService = m_serviceRegistry.getFileFolderService();
m_searchService = m_serviceRegistry.getSearchService();
m_namespaceService = m_serviceRegistry.getNamespaceService();
m_dictionaryService = m_serviceRegistry.getDictionaryService();
m_mimetypeService = m_serviceRegistry.getMimetypeService();
m_lockService = m_serviceRegistry.getLockService();
m_authService = authService;
}
/**
* Return the authentication service
*
* @return AuthenticationService
*/
public final AuthenticationService getAuthenticationService()
{
return m_authService;
}
/**
* Return the service registry
*
* @return ServiceRegistry
*/
public final ServiceRegistry getServiceRegistry()
{
return m_serviceRegistry;
}
/**
* Return the node service
*
* @return NodeService
*/
public final NodeService getNodeService()
{
return m_nodeService;
}
public FileFolderService getFileFolderService()
{
return m_fileFolderService;
}
/**
* Return the search service
*
* @return SearchService
*/
public final SearchService getSearchService()
{
return m_searchService;
}
/**
* Return the namespace service
*
* @return NamespaceService
*/
public final NamespaceService getNamespaceService()
{
return m_namespaceService;
}
/**
* Return the dictionary service
*
* @return DictionaryService
*/
public final DictionaryService getDictionaryService()
{
return m_dictionaryService;
}
/**
* Return the mimetype service
*
* @return MimetypeService
*/
public final MimetypeService getMimetypeService()
{
return m_mimetypeService;
}
/**
* Return the lock service
*
* @return LockService
*/
public final LockService getLockService()
{
return m_lockService;
}
/**
* Return the copy service
*
* @return CopyService
*/
public final CopyService getCopyService()
{
return getServiceRegistry().getCopyService();
}
/**
* Split the path into seperate directory path and file name strings.
* If the path is not empty, then there will always be an entry for the filename
*
* @param path Full path string.
* @return Returns a String[2] with the folder path and file path.
*/
public final String[] splitPath(String path)
{
if (path == null)
throw new IllegalArgumentException("path may not be null");
// Create an array of strings to hold the path and file name strings
String[] pathStr = new String[] {"", ""};
// Check if the path has a trailing seperator, if so then there is no file name.
int pos = path.lastIndexOf(PathSeperatorChar);
if (pos == -1 || pos == (path.length() - 1))
{
// Set the path string in the returned string array
pathStr[1] = path;
}
else
{
pathStr[0] = path.substring(0, pos);
pathStr[1] = path.substring(pos + 1);
}
// Return the path strings
return pathStr;
}
/**
* Split the path into all the component directories and filename
*
* @param path String
* @return String[]
*/
public final List<String> splitAllPaths(String path)
{
if (path == null || path.length() == 0)
{
return Collections.emptyList();
}
// split the path
StringTokenizer token = new StringTokenizer(path, PathSeperator);
List<String> results = new ArrayList<String>(10);
while (token.hasMoreTokens())
{
results.add(token.nextToken());
}
return results;
}
/**
* Get the file info for the given paths
*
* @param rootNodeRef the acting webdav root
* @param path the path to search for
* @param servletPath the base servlet path, which may be null or empty
* @return Return the file info for the path
* @throws FileNotFoundException if the path doesn't refer to a valid node
*/
public final FileInfo getNodeForPath(NodeRef rootNodeRef, String path, String servletPath) throws FileNotFoundException
{
if (rootNodeRef == null)
{
throw new IllegalArgumentException("Root node may not be null");
}
else if (path == null)
{
throw new IllegalArgumentException("Path may not be null");
}
FileFolderService fileFolderService = getFileFolderService();
// Check for the root path
if ( path.length() == 0 || path.equals(PathSeperator) || EqualsHelper.nullSafeEquals(path, servletPath))
{
return fileFolderService.getFileInfo(rootNodeRef);
}
// remove the servlet path from the path
if (servletPath != null && servletPath.length() > 0 && path.startsWith(servletPath))
{
// Strip the servlet path from the relative path
path = path.substring(servletPath.length());
}
// split the paths up
List<String> splitPath = splitAllPaths(path);
// find it
FileInfo fileInfo = m_fileFolderService.resolveNamePath(rootNodeRef, splitPath);
// done
if (logger.isDebugEnabled())
{
logger.debug("Fetched node for path: \n" +
" root: " + rootNodeRef + "\n" +
" path: " + path + "\n" +
" servlet path: " + servletPath + "\n" +
" result: " + fileInfo);
}
return fileInfo;
}
public final FileInfo getParentNodeForPath(NodeRef rootNodeRef, String path, String servletPath) throws FileNotFoundException
{
if (rootNodeRef == null)
{
throw new IllegalArgumentException("Root node may not be null");
}
else if (path == null)
{
throw new IllegalArgumentException("Path may not be null");
}
// shorten the path
String[] paths = splitPath(path);
return getNodeForPath(rootNodeRef, paths[0], servletPath);
}
/**
* Return the relative path for the node walking back to the specified root node
*
* @param rootNodeRef the root below which the path will be valid
* @param nodeRef the node's path to get
* @return Returns string of form <b>/A/B/C</b> where C represents the from node and
*/
public final String getPathFromNode(NodeRef rootNodeRef, NodeRef nodeRef) throws FileNotFoundException
{
// Check if the nodes are valid, or equal
if (rootNodeRef == null || nodeRef == null)
throw new IllegalArgumentException("Invalid node(s) in getPathFromNode call");
// short cut if the path node is the root node
if (rootNodeRef.equals(nodeRef))
return "";
FileFolderService fileFolderService = getFileFolderService();
// get the path elements
List<FileInfo> pathInfos = fileFolderService.getNamePath(rootNodeRef, nodeRef);
// build the path string
StringBuilder sb = new StringBuilder(pathInfos.size() * 20);
for (FileInfo fileInfo : pathInfos)
{
sb.append(WebDAVHelper.PathSeperatorChar);
sb.append(fileInfo.getName());
}
// done
if (logger.isDebugEnabled())
{
logger.debug("Build name path for node: \n" +
" root: " + rootNodeRef + "\n" +
" target: " + nodeRef + "\n" +
" path: " + sb);
}
return sb.toString();
}
/**
* Make an ETag value for a node using the GUID and modify date/time
*
* @param node NodeRef
* @return String
*/
public final String makeETag(NodeRef node)
{
// Get the modify date/time property for the node
StringBuilder etag = new StringBuilder();
makeETagString(node, etag);
return etag.toString();
}
/**
* Make an ETag value for a node using the GUID and modify date/time
*
* @param node NodeRef
* @return String
*/
public final String makeQuotedETag(NodeRef node)
{
StringBuilder etag = new StringBuilder();
etag.append("\"");
makeETagString(node, etag);
etag.append("\"");
return etag.toString();
}
/**
* Make an ETag value for a node using the GUID and modify date/time
*
* @param node NodeRef
* @param str StringBuilder
*/
protected final void makeETagString(NodeRef node, StringBuilder etag)
{
// Get the modify date/time property for the node
Object modVal = getNodeService().getProperty(node, ContentModel.PROP_MODIFIED);
etag.append(node.getId());
if ( modVal != null)
{
etag.append("_");
etag.append(DefaultTypeConverter.INSTANCE.longValue(modVal));
}
}
/**
* Return the null XML attribute list
*
* @return AttributesImpl
*/
public final AttributesImpl getNullAttributes()
{
return m_nullAttribs;
}
}

View File

@@ -0,0 +1,520 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.transaction.TransactionUtil;
import org.alfresco.repo.transaction.TransactionUtil.TransactionWork;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.DocumentHelper;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.w3c.dom.Document;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* Abstract base class for all the WebDAV method handling classes
*
* @author gavinc
*/
public abstract class WebDAVMethod
{
// Log output
protected static Log logger = LogFactory.getLog("org.alfresco.webdav.protocol");
// Output formatted XML in the response
private static final boolean XMLPrettyPrint = true;
// Servlet request/response
protected HttpServletRequest m_request;
protected HttpServletResponse m_response;
// WebDAV helper
protected WebDAVHelper m_davHelper;
// Root node
protected NodeRef m_rootNodeRef;
// Repository path
protected String m_strPath = null;
/**
* Default constructor
*/
public WebDAVMethod()
{
}
/**
* Set the request/response details
*
* @param req HttpServletRequest
* @param resp HttpServletResponse
* @param registry ServiceRegistry
* @param rootNode NodeRef
*/
public void setDetails(HttpServletRequest req, HttpServletResponse resp, WebDAVHelper davHelper, NodeRef rootNode)
{
m_request = req;
m_response = resp;
m_davHelper = davHelper;
m_rootNodeRef = rootNode;
m_strPath = WebDAV.getRepositoryPath(req);
}
/**
* Executes the method
*/
public void execute() throws WebDAVServerException
{
// Parse the HTTP headers
parseRequestHeaders();
// Parse the HTTP body
parseRequestBody();
TransactionWork<WebDAVServerException> executeWork = new TransactionWork<WebDAVServerException>()
{
public WebDAVServerException doWork() throws Exception
{
executeImpl();
return null;
}
};
try
{
// Execute the method
TransactionService transactionService = getTransactionService();
TransactionUtil.executeInUserTransaction(transactionService, executeWork);
}
catch (AccessDeniedException e)
{
// Return a forbidden status
throw new WebDAVServerException(HttpServletResponse.SC_UNAUTHORIZED, e);
}
catch (Throwable e)
{
Throwable cause = e.getCause();
if (cause instanceof WebDAVServerException)
{
throw (WebDAVServerException) cause;
}
else
{
// Convert error to a server error
throw new WebDAVServerException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
}
}
}
/**
* Access the content repository to satisfy the request and generates the appropriate WebDAV
* response.
*
* @throws WebDAVServerException a general server exception
* @throws Exception any unhandled exception
*/
protected abstract void executeImpl() throws WebDAVServerException, Exception;
/**
* Parses the given request body represented as an XML document and sets any necessary context
* ready for execution.
*/
protected abstract void parseRequestBody() throws WebDAVServerException;
/**
* Parses the HTTP headers of the request and sets any necessary context ready for execution.
*/
protected abstract void parseRequestHeaders() throws WebDAVServerException;
/**
* Retrieves the request body as an XML document
*
* @return The body of the request as an XML document or null if there isn't a body
*/
protected Document getRequestBodyAsDocument() throws WebDAVServerException
{
Document body = null;
if (m_request.getContentLength() > 0)
{
// TODO: Do we need to do anything for chunking support?
try
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
body = builder.parse(new InputSource(m_request.getReader()));
}
catch (ParserConfigurationException e)
{
throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST, e);
}
catch (SAXException e)
{
throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST, e);
}
catch (IOException e)
{
throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST, e);
}
}
return body;
}
/**
* Returns the lock token present in the If header
*
* @return The lock token present in the If header
*/
protected String parseIfHeader() throws WebDAVServerException
{
String strLockToken = null;
String strIf = m_request.getHeader(WebDAV.HEADER_IF);
if (logger.isDebugEnabled())
logger.debug("Parsing If header: " + strIf);
if (strIf != null && strIf.length() > 0)
{
if (strIf.startsWith("(<"))
{
// Parse the tokens (only get the first one though)
int idx = strIf.indexOf(">");
if (idx != -1)
{
try
{
strLockToken = strIf.substring(WebDAV.OPAQUE_LOCK_TOKEN.length() + 2, idx);
}
catch (IndexOutOfBoundsException e)
{
logger.warn("Failed to parse If header: " + strIf);
}
}
else
{
throw new WebDAVServerException(HttpServletResponse.SC_BAD_REQUEST);
}
// Print a warning if there are other tokens detected
if (strIf.length() > idx + 2)
{
logger.warn("The If header contained more than one lock token, only one is supported");
}
}
else if (strIf.startsWith("<"))
{
logger.warn("Tagged lists in the If header are not supported");
}
else if (strIf.startsWith("(["))
{
logger.warn("ETags in the If header are not supported");
}
}
return strLockToken;
}
/**
* Return the WebDAV protocol helper
*
* @return WebDAVHelper
*/
protected final WebDAVHelper getDAVHelper()
{
return m_davHelper;
}
/**
* Return the service registry
*
* @return ServiceRegistry
*/
protected final ServiceRegistry getServiceRegistry()
{
return m_davHelper.getServiceRegistry();
}
/**
* Convenience method to return the transaction service
*
* @return TransactionService
*/
protected final TransactionService getTransactionService()
{
return m_davHelper.getServiceRegistry().getTransactionService();
}
/**
* Convenience method to return the node service
*
* @return NodeService
*/
protected final NodeService getNodeService()
{
return m_davHelper.getNodeService();
}
/**
* @return Returns the general file/folder manipulation service
*/
protected final FileFolderService getFileFolderService()
{
return m_davHelper.getFileFolderService();
}
/**
* Convenience method to return the content service
*
* @return ContentService
*/
protected final ContentService getContentService()
{
return m_davHelper.getServiceRegistry().getContentService();
}
/**
* Convenience method to return the mimetype service
*
* @return MimetypeService
*/
protected final MimetypeService getMimetypeService()
{
return m_davHelper.getMimetypeService();
}
/**
* Convenience method to return the lock service
*
* @return LockService
*/
protected final LockService getLockService()
{
return m_davHelper.getLockService();
}
/**
* Convenience method to return the authentication service
*
* @return AuthenticationService
*/
protected final AuthenticationService getAuthenticationService()
{
return m_davHelper.getAuthenticationService();
}
/**
* @return Returns the path of the servlet
*/
protected final String getServletPath()
{
return m_request.getServletPath();
}
/**
* Return the root node
*
* @return NodeRef
*/
protected final NodeRef getRootNodeRef()
{
return m_rootNodeRef;
}
/**
* Return the relative path
*
* @return String
*/
protected final String getPath()
{
return m_strPath;
}
/**
* Create an XML writer for the response
*
* @return XMLWriter
* @exception IOException
*/
protected final XMLWriter createXMLWriter() throws IOException
{
// Check if debug output or XML pretty printing is enabled
XMLWriter writer = null;
if (XMLPrettyPrint == true || logger.isDebugEnabled())
{
writer = new XMLWriter(m_response.getWriter(), OutputFormat.createPrettyPrint());
}
else
{
writer = new XMLWriter(m_response.getWriter(), OutputFormat.createCompactFormat());
}
// Return the writer
return writer;
}
/**
* Generates the lock discovery XML response
*
* @param xml XMLWriter
* @param lockNode NodeRef
*/
protected void generateLockDiscoveryXML(XMLWriter xml, NodeRef lockNode) throws Exception
{
Attributes nullAttr= getDAVHelper().getNullAttributes();
if (lockNode != null)
{
// Get the lock details
NodeService nodeService = getNodeService();
String owner = (String) nodeService.getProperty(lockNode, ContentModel.PROP_LOCK_OWNER);
Date expiryDate = (Date) nodeService.getProperty(lockNode, ContentModel.PROP_EXPIRY_DATE);
// Output the XML response
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_DISCOVERY, WebDAV.XML_NS_LOCK_DISCOVERY, nullAttr);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_ACTIVE_LOCK, WebDAV.XML_NS_ACTIVE_LOCK, nullAttr);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_NS_LOCK_TYPE, nullAttr);
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_WRITE));
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TYPE, WebDAV.XML_NS_LOCK_TYPE);
// NOTE: We only do exclusive lock tokens at the moment
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE, nullAttr);
xml.write(DocumentHelper.createElement(WebDAV.XML_NS_EXCLUSIVE));
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_SCOPE, WebDAV.XML_NS_LOCK_SCOPE);
// NOTE: We only support one level of lock at the moment
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_DEPTH, WebDAV.XML_NS_DEPTH, nullAttr);
xml.write(WebDAV.ZERO);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_DEPTH, WebDAV.XML_NS_DEPTH);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_OWNER, WebDAV.XML_NS_OWNER, nullAttr);
xml.write(owner);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_OWNER, WebDAV.XML_NS_OWNER);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_TIMEOUT, WebDAV.XML_NS_TIMEOUT, nullAttr);
// Output the expiry time
String strTimeout = WebDAV.INFINITE;
if (expiryDate != null)
{
long timeoutRemaining = (expiryDate.getTime() - System.currentTimeMillis())/1000L;
strTimeout = WebDAV.SECOND + timeoutRemaining;
}
xml.write(strTimeout);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_TIMEOUT, WebDAV.XML_NS_TIMEOUT);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TOKEN, WebDAV.XML_NS_LOCK_TOKEN, nullAttr);
xml.startElement(WebDAV.DAV_NS, WebDAV.XML_HREF, WebDAV.XML_NS_HREF, nullAttr);
xml.write(WebDAV.makeLockToken(lockNode, owner));
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_HREF, WebDAV.XML_NS_HREF);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_TOKEN, WebDAV.XML_NS_LOCK_TOKEN);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_ACTIVE_LOCK, WebDAV.XML_NS_ACTIVE_LOCK);
xml.endElement(WebDAV.DAV_NS, WebDAV.XML_LOCK_DISCOVERY, WebDAV.XML_NS_LOCK_DISCOVERY);
}
}
/**
* Generates a list of namespace declarations for the response
*/
protected String generateNamespaceDeclarations(HashMap<String,String> nameSpaces)
{
StringBuilder ns = new StringBuilder();
ns.append(" ");
ns.append(WebDAV.XML_NS);
ns.append(":");
ns.append(WebDAV.DAV_NS);
ns.append("=\"");
ns.append(WebDAV.DEFAULT_NAMESPACE_URI);
ns.append("\"");
// Add additional namespaces
if ( nameSpaces != null)
{
Iterator<String> namespaceList = nameSpaces.keySet().iterator();
while (namespaceList.hasNext())
{
String strNamespaceUri = namespaceList.next();
String strNamespaceName = nameSpaces.get(strNamespaceUri);
ns.append(" ").append(WebDAV.XML_NS).append(":").append(strNamespaceName).append("=\"");
ns.append(strNamespaceUri).append("\" ");
}
}
return ns.toString();
}
}

View File

@@ -0,0 +1,156 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
/**
* Class to represent a WebDAV property
*
* @author gavinc
*/
public class WebDAVProperty
{
private String m_strName = null;
private String m_strNamespaceUri = WebDAV.DEFAULT_NAMESPACE_URI;
private String m_strNamespaceName = null;
private String m_strValue = null;
/**
* Constructs a WebDAVProperty
*
* @param strName
* @param strNamespaceUri
* @param strNamespaceName
* @param strValue
*/
public WebDAVProperty(String strName, String strNamespaceUri, String strNamespaceName, String strValue)
{
this(strName, strNamespaceUri, strNamespaceName);
m_strValue = strValue;
}
/**
* Constructs a WebDAVProperty
*
* @param strName
* @param strNamespaceUri
* @param strNamespaceName
* @param strValue
*/
public WebDAVProperty(String strName, String strNamespaceUri, String strNamespaceName)
{
this(strName);
m_strNamespaceUri = strNamespaceUri;
m_strNamespaceName = strNamespaceName;
}
/**
* Constructs a WebDAVProperty with the default namespace details
*
* @param strName
*/
public WebDAVProperty(String strName)
{
m_strName = strName;
}
/**
* Returns the name of the property
*
* @return The name of the property
*/
public String getName()
{
return m_strName;
}
/**
* Returns the namespace URI for this property
*
* @return The namespace URI for this property
*/
public String getNamespaceUri()
{
return m_strNamespaceUri;
}
/**
* Determine if the property has a namespace
*
* @return boolean
*/
public final boolean hasNamespaceName()
{
return m_strNamespaceName != null ? true : false;
}
/**
* Returns the namespace name for this property
*
* @return The namespace name for this property
*/
public String getNamespaceName()
{
return m_strNamespaceName;
}
/**
* Returns the value of this property
*
* @return The value of this property
*/
public String getValue()
{
return m_strValue;
}
/**
* Sets the property's value
*
* @param strValue The new value
*/
public void setValue(String strValue)
{
m_strValue = strValue;
}
/**
* Return the property as a string
*
* @return String
*/
public String toString()
{
StringBuilder str = new StringBuilder();
str.append("[");
str.append(getName());
str.append("=");
str.append(getValue());
str.append(",URI=");
str.append(getNamespaceUri());
if ( hasNamespaceName())
{
str.append(",");
str.append(getNamespaceName());
}
return str.toString();
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
import javax.servlet.http.HttpServletResponse;
/**
* Exception class that represents an error in the WebDAV protocol layer
*
* @author gavinc
*/
public class WebDAVServerException extends Exception
{
private static final long serialVersionUID = -2949418282738082368L;
private int m_httpStatusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
private Throwable m_cause = null;
/**
* Constructs a WebDAVException
*
* @param httpStatusCode The HTTP status code
*/
public WebDAVServerException(int httpStatusCode)
{
this(httpStatusCode, null);
}
/**
* Constructs a WebDAVException
*
* @param httpStatusCode The HTTP status code
* @param cause The cause of this exception
*/
public WebDAVServerException(int httpStatusCode, Throwable cause)
{
super(Integer.toString(httpStatusCode));
m_httpStatusCode = httpStatusCode;
m_cause = cause;
}
/**
* Returns the HTTP status code
*
* @return The HTTP status code
*/
public int getHttpStatusCode()
{
return m_httpStatusCode;
}
/**
* Returns the cause of this exception
*
* @return The cause of this exception
*/
public Throwable getCause()
{
return m_cause;
}
/**
* @see java.lang.Object#toString()
*/
public String toString()
{
String strErrorMsg = "HTTP Status Code: " + m_httpStatusCode;
if (m_cause != null)
{
strErrorMsg = strErrorMsg + " caused by: " + m_cause.toString();
}
return strErrorMsg;
}
}

View File

@@ -0,0 +1,313 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain an
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.UserTransaction;
import org.alfresco.filesys.server.config.ServerConfiguration;
import org.alfresco.filesys.server.core.InvalidDeviceInterfaceException;
import org.alfresco.filesys.server.core.ShareType;
import org.alfresco.filesys.server.core.SharedDevice;
import org.alfresco.filesys.server.core.SharedDeviceList;
import org.alfresco.filesys.server.filesys.DiskInterface;
import org.alfresco.filesys.server.filesys.DiskSharedDevice;
import org.alfresco.filesys.smb.server.repo.ContentContext;
import org.alfresco.filesys.smb.server.repo.ContentDiskInterface;
import org.alfresco.repo.webdav.auth.AuthenticationFilter;
import org.alfresco.repo.webdav.auth.WebDAVUser;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* Servlet that accepts WebDAV requests for the hub. The request is served by the hub's content
* repository framework and the response sent back using the WebDAV protocol.
*
* @author gavinc
*/
public class WebDAVServlet extends HttpServlet
{
public static final String WEBDAV_PREFIX = "webdav";
private static final long serialVersionUID = 6900069445027527165L;
// Logging
private static Log logger = LogFactory.getLog("org.alfresco.webdav.protocol");
// Error message(s)
private static final String INTERNAL_SERVER_ERROR = "Internal Server Error: ";
// Service registry, used by methods to find services to process requests
private ServiceRegistry m_serviceRegistry;
// Transaction service, each request is wrapped in a transaction
private TransactionService m_transactionService;
// WebDAV method handlers
private Hashtable<String,Class> m_davMethods;
// Root node
private NodeRef m_rootNodeRef;
// WebDAV helper class
private WebDAVHelper m_davHelper;
/**
* @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException
{
long startTime = 0;
if (logger.isDebugEnabled())
{
startTime = System.currentTimeMillis();
}
// Wrap the request in a transaction
UserTransaction tx = m_transactionService.getUserTransaction();
try
{
// Create the appropriate WebDAV method for the request and execute it
WebDAVMethod method = createMethod(request, response);
if (method == null)
{
// Debug
if ( logger.isErrorEnabled())
logger.error("WebDAV method not implemented - " + request.getMethod());
// Return an error status
response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
return;
}
else if ( method.getRootNodeRef() == null)
{
// Debug
if ( logger.isErrorEnabled())
logger.error("No root node for request");
// Return an error status
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
// Execute the WebDAV request, wrapped in a transaction
tx.begin();
method.execute();
tx.commit();
}
catch (Exception e)
{
// Whatever happened we need to rollback the transaction
try
{
tx.rollback();
}
catch (Exception ex)
{
logger.warn("Failed to rollback transaction", ex);
}
// Work out how to handle the error
if (e instanceof WebDAVServerException)
{
WebDAVServerException error = (WebDAVServerException) e;
if (error.getCause() != null)
{
logger.error(INTERNAL_SERVER_ERROR, error.getCause());
}
if (logger.isDebugEnabled())
{
// Show what status code the method sent back
logger.debug(request.getMethod() + " is returning status code: " + error.getHttpStatusCode());
}
if (response.isCommitted())
{
logger.warn("Could not return the status code to the client as the response has already been committed!");
}
else
{
response.sendError(error.getHttpStatusCode());
}
}
else
{
logger.error(INTERNAL_SERVER_ERROR, e);
if (response.isCommitted())
{
logger.warn("Could not return the internal server error code to the client as the response has already been committed!");
}
else
{
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
}
finally
{
if (logger.isDebugEnabled())
{
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
logger.debug(request.getMethod() + " took " + duration + "ms to execute");
}
}
}
/**
* Create a WebDAV method handler
*
* @param request HttpServletRequest
* @param response HttpServletResponse
* @return WebDAVMethod
*/
private WebDAVMethod createMethod(HttpServletRequest request, HttpServletResponse response)
{
// Get the type of the current request
String strHttpMethod = request.getMethod();
if (logger.isDebugEnabled())
logger.debug("WebDAV request " + strHttpMethod + " on path "
+ request.getRequestURI());
Class methodClass = m_davMethods.get(strHttpMethod);
WebDAVMethod method = null;
if ( methodClass != null)
{
try
{
// Create the handler method
method = (WebDAVMethod) methodClass.newInstance();
method.setDetails(request, response, m_davHelper, m_rootNodeRef);
}
catch (Exception ex)
{
// Debug
if ( logger.isDebugEnabled())
logger.debug(ex);
}
}
// Return the WebDAV method handler, or null if not supported
return method;
}
/**
* Initialize the servlet
*
* @param config ServletConfig
* @exception ServletException
*/
public void init(ServletConfig config) throws ServletException
{
super.init(config);
// Get service registry
WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
m_serviceRegistry = (ServiceRegistry)context.getBean(ServiceRegistry.SERVICE_REGISTRY);
m_transactionService = m_serviceRegistry.getTransactionService();
AuthenticationService authService = (AuthenticationService) context.getBean("authenticationService");
// Create the WebDAV helper
m_davHelper = new WebDAVHelper(m_serviceRegistry, authService);
// Initialize the root node
//
// For now we get the details from the first available shared filesystem that is configured
ServerConfiguration fileSrvConfig = (ServerConfiguration) context.getBean(ServerConfiguration.SERVER_CONFIGURATION);
if ( fileSrvConfig == null)
throw new ServletException("File server configuration not available");
DiskSharedDevice filesys = fileSrvConfig.getPrimaryFilesystem();
if ( filesys != null)
{
// Get the root node from the filesystem
ContentContext contentCtx = (ContentContext) filesys.getContext();
m_rootNodeRef = contentCtx.getRootNode();
}
else
{
logger.warn("No default root node for WebDAV, using home node only");
}
// Create the WebDAV methods table
m_davMethods = new Hashtable<String,Class>();
m_davMethods.put(WebDAV.METHOD_PROPFIND, PropFindMethod.class);
m_davMethods.put(WebDAV.METHOD_COPY, CopyMethod.class);
m_davMethods.put(WebDAV.METHOD_DELETE, DeleteMethod.class);
m_davMethods.put(WebDAV.METHOD_GET, GetMethod.class);
m_davMethods.put(WebDAV.METHOD_HEAD, HeadMethod.class);
m_davMethods.put(WebDAV.METHOD_LOCK, LockMethod.class);
m_davMethods.put(WebDAV.METHOD_MKCOL, MkcolMethod.class);
m_davMethods.put(WebDAV.METHOD_MOVE, MoveMethod.class);
m_davMethods.put(WebDAV.METHOD_OPTIONS, OptionsMethod.class);
m_davMethods.put(WebDAV.METHOD_POST, PostMethod.class);
m_davMethods.put(WebDAV.METHOD_PUT, PutMethod.class);
m_davMethods.put(WebDAV.METHOD_UNLOCK, UnlockMethod.class);
}
}

View File

@@ -0,0 +1,199 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav.auth;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.codec.binary.Base64;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* WebDAV Authentication Filter Class
*
* @author GKSpencer
*/
public class AuthenticationFilter implements Filter
{
// Authenticated user session object name
public final static String AUTHENTICATION_USER = "_alfDAVAuthTicket";
// Servlet context
private ServletContext m_context;
// Various services required by NTLM authenticator
private AuthenticationService m_authService;
private AuthenticationComponent m_authComponent;
private PersonService m_personService;
private NodeService m_nodeService;
/**
* Initialize the filter
*
* @param config FitlerConfig
* @exception ServletException
*/
public void init(FilterConfig config) throws ServletException
{
// Save the context
m_context = config.getServletContext();
// Setup the authentication context
WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(m_context);
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
m_nodeService = serviceRegistry.getNodeService();
m_authService = (AuthenticationService) ctx.getBean("authenticationService");
m_authComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
m_personService = (PersonService) ctx.getBean("personService");
}
/**
* Run the authentication filter
*
* @param req ServletRequest
* @param resp ServletResponse
* @param chain FilterChain
* @exception ServletException
* @exception IOException
*/
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException,
ServletException
{
// Assume it's an HTTP request
HttpServletRequest httpReq = (HttpServletRequest) req;
HttpServletResponse httpResp = (HttpServletResponse) resp;
// Get the user details object from the session
WebDAVUser user = (WebDAVUser) httpReq.getSession().getAttribute(AUTHENTICATION_USER);
if (user == null)
{
// Get the authorization header
String authHdr = httpReq.getHeader("Authorization");
if ( authHdr != null && authHdr.length() > 5 && authHdr.substring(0,5).equalsIgnoreCase("BASIC"))
{
// Basic authentication details present
String basicAuth = new String(Base64.decodeBase64(authHdr.substring(5).getBytes()));
// Split the username and password
String username = null;
String password = null;
int pos = basicAuth.indexOf(":");
if ( pos != -1)
{
username = basicAuth.substring(0, pos);
password = basicAuth.substring(pos + 1);
}
else
{
username = basicAuth;
password = "";
}
try
{
// Authenticate the user
m_authService.authenticate(username, password.toCharArray());
// Get the users home folder
NodeRef homeSpaceRef = (NodeRef) m_nodeService.getProperty(m_personService.getPerson(username), ContentModel.PROP_HOMEFOLDER);
// Setup User object and Home space ID etc.
user = new WebDAVUser(username, m_authService.getCurrentTicket(), homeSpaceRef);
httpReq.getSession().setAttribute(AUTHENTICATION_USER, user);
}
catch ( AuthenticationException ex)
{
// Do nothing, user object will be null
}
}
// Check if the user is authenticated, if not then prompt again
if ( user == null)
{
// No user/ticket, force the client to prompt for logon details
httpResp.setHeader("WWW-Authenticate", "BASIC");
httpResp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
httpResp.flushBuffer();
return;
}
}
else
{
// Setup the authentication context
m_authService.validate(user.getTicket());
// Set the current locale
// I18NUtil.setLocale(Application.getLanguage(httpRequest.getSession()));
}
// Chain other filters
chain.doFilter(req, resp);
}
/**
* Cleanup filter resources
*/
public void destroy()
{
// Nothing to do
}
}

View File

@@ -0,0 +1,130 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webdav.auth;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* WebDAV User Class
*
* <p>Contains the details of an authenticated WebDAV user
*
* @author GKSpencer
*/
public class WebDAVUser
{
// User name
private String m_userName;
// Authentication ticket
private String m_ticket;
// User home node
private NodeRef m_homeNode;
/**
* Class constructor
*
* @param user String
* @param ticket String
* @param homeNode NodeRef
*/
public WebDAVUser(String user, String ticket, NodeRef homeNode)
{
m_userName = user;
m_ticket = ticket;
m_homeNode = homeNode;
}
/**
* Return the user name
*
* @return String
*/
public final String getUserName()
{
return m_userName;
}
/**
* Return the ticket
*
* @return String
*/
public final String getTicket()
{
return m_ticket;
}
/**
* Check if the user has a home node
*
* @return boolean
*/
public final boolean hasHomeNode()
{
return m_homeNode != null ? true : false;
}
/**
* Return the user home node
*
* @return NodeRef
*/
public final NodeRef getHomeNode()
{
return m_homeNode;
}
/**
* Set the home folder node for this user
*
* @param homeNode NodeRef
*/
protected final void setHomeNode(NodeRef homeNode)
{
m_homeNode = homeNode;
}
/**
* Return the user details as a string
*
* @return String
*/
public String toString()
{
StringBuilder str = new StringBuilder();
str.append("[");
str.append(getUserName());
str.append(":");
str.append(getTicket());
if ( hasHomeNode())
{
str.append(",Home=");
str.append(getHomeNode());
}
str.append("]");
return str.toString();
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the GNU Lesser General Public License as
* published by the Free Software Foundation; either version
* 2.1 of the License, or (at your option) any later version.
* You may obtain a copy of the License at
*
* http://www.gnu.org/licenses/lgpl.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
/**
* Abstract base class for all web service implementations, provides support for common
* service injection
*
* @author gavinc
*/
public abstract class AbstractWebService
{
protected NodeService nodeService;
protected ContentService contentService;
protected SearchService searchService;
protected NamespaceService namespaceService;
/**
* Sets the instance of the NodeService to be used
*
* @param nodeService The NodeService
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* Sets the ContentService instance to use
*
* @param contentSvc The ContentService
*/
public void setContentService(ContentService contentSvc)
{
this.contentService = contentSvc;
}
/**
* Sets the instance of the SearchService to be used
*
* @param searchService The SearchService
*/
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
/**
* Sets the instance of the NamespaceService to be used
*
* @param namespaceService The NamespaceService
*/
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
}

View File

@@ -0,0 +1,569 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.webservice.repository.UpdateResult;
import org.alfresco.repo.webservice.types.CML;
import org.alfresco.repo.webservice.types.CMLAddAspect;
import org.alfresco.repo.webservice.types.CMLAddChild;
import org.alfresco.repo.webservice.types.CMLCopy;
import org.alfresco.repo.webservice.types.CMLCreate;
import org.alfresco.repo.webservice.types.CMLCreateAssociation;
import org.alfresco.repo.webservice.types.CMLDelete;
import org.alfresco.repo.webservice.types.CMLMove;
import org.alfresco.repo.webservice.types.CMLRemoveAspect;
import org.alfresco.repo.webservice.types.CMLRemoveAssociation;
import org.alfresco.repo.webservice.types.CMLRemoveChild;
import org.alfresco.repo.webservice.types.CMLUpdate;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.ParentReference;
import org.alfresco.repo.webservice.types.Predicate;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.service.cmr.repository.CopyService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.PropertyMap;
/**
* @author Roy Wetherall
*/
public class CMLUtil
{
private static final String CREATE = "create";
private static final String ADD_ASPECT = "addAspect";
private static final String REMOVE_ASPECT = "removeAspect";
private static final String UPDATE = "update";
private static final String DELETE = "delete";
private static final String MOVE = "move";
private static final String COPY = "copy";
private static final String ADD_CHILD = "addChild";
private static final String REMOVE_CHILD = "removeChild";
private static final String CREATE_ASSOCIATION = "createAssociation";
private static final String REMOVE_ASSOCIATION = "removeAssociation";
private NodeService nodeService;
private SearchService searchService;
private NamespaceService namespaceService;
private CopyService copyService;
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
public void setCopyService(CopyService copyService)
{
this.copyService = copyService;
}
/**
* Execute a cml update query.
*
* @param cml the cml objects
* @return the update result
*/
public UpdateResult[] executeCML(CML cml)
{
ExecutionContext context = new ExecutionContext();
List<UpdateResult> results = new ArrayList<UpdateResult>();
// Execute creates
CMLCreate[] creates = cml.getCreate();
if (creates != null)
{
for (CMLCreate create : creates)
{
executeCMLCreate(create, context, results);
}
}
// Exceute add aspect
CMLAddAspect[] addAspects = cml.getAddAspect();
if (addAspects != null)
{
for (CMLAddAspect addAspect : addAspects)
{
executeCMLAddAspect(addAspect, context, results);
}
}
// Execeute remove aspect
CMLRemoveAspect[] removeAspects = cml.getRemoveAspect();
if (removeAspects != null)
{
for (CMLRemoveAspect removeAspect : removeAspects)
{
executeCMLRemoveAspect(removeAspect, context, results);
}
}
// Execute update
CMLUpdate[] updates = cml.getUpdate();
if (updates != null)
{
for (CMLUpdate update : updates)
{
executeCMLUpdate(update, context, results);
}
}
// Execute delete
CMLDelete[] deletes = cml.getDelete();
if (deletes != null)
{
for (CMLDelete delete : deletes)
{
executeCMLDelete(delete, context, results);
}
}
// Execute move
CMLMove[] moves = cml.getMove();
if (moves != null)
{
for (CMLMove move : moves)
{
executeCMLMove(move, context, results);
}
}
// Execute copy
CMLCopy[] copies = cml.getCopy();
if (copies != null)
{
for (CMLCopy copy : copies)
{
executeCMLCopy(copy, context, results);
}
}
// Execute addChild
CMLAddChild[] addChildren = cml.getAddChild();
if (addChildren != null)
{
for (CMLAddChild addChild : addChildren)
{
executeCMLAddChild(addChild, context, results);
}
}
// Execute removeChild
CMLRemoveChild[] removeChildren = cml.getRemoveChild();
if (removeChildren != null)
{
for (CMLRemoveChild removeChild : removeChildren)
{
executeCMLRemoveChild(removeChild, context, results);
}
}
// Execute createAssociation
CMLCreateAssociation[] createAssocs = cml.getCreateAssociation();
if (createAssocs != null)
{
for (CMLCreateAssociation createAssoc : createAssocs)
{
executeCMLCreateAssociation(createAssoc, context, results);
}
}
// Execute removeAssociation
CMLRemoveAssociation[] removeAssocs = cml.getRemoveAssociation();
if (removeAssocs != null)
{
for (CMLRemoveAssociation removeAssoc : removeAssocs)
{
executeCMLRemoveAssociation(removeAssoc, context, results);
}
}
return results.toArray(new UpdateResult[results.size()]);
}
/**
*
* @param create
* @param result
*/
private void executeCMLCreate(CMLCreate create, ExecutionContext context, List<UpdateResult> results)
{
// Get the detail of the parent
ParentReference parentReference = create.getParent();
NodeRef parentNodeRef = Utils.convertToNodeRef(
parentReference,
this.nodeService,
this.searchService,
this.namespaceService);
QName assocTypeQName = QName.createQName(parentReference.getAssociationType());
QName assocQName = QName.createQName(parentReference.getChildName());
// Get the type of the node to create
QName nodeTypeQName = QName.createQName(create.getType());
// Get the properties
PropertyMap properties = getPropertyMap(create.getProperty());
// Create the new node
NodeRef nodeRef = this.nodeService.createNode(parentNodeRef, assocTypeQName, assocQName, nodeTypeQName, properties).getChildRef();
// Store the node ref in the execution context (if appropraite)
String id = create.getId();
if (id != null && id.length() != 0)
{
context.addId(id, nodeRef);
}
results.add(createResult(CREATE, null, nodeRef));
}
private PropertyMap getPropertyMap(NamedValue[] namedValues)
{
PropertyMap properties = new PropertyMap();
if (namedValues != null)
{
for (NamedValue value : namedValues)
{
QName qname = QName.createQName(value.getName());
properties.put(qname, value.getValue());
}
}
return properties;
}
private UpdateResult createResult(String cmd, NodeRef sourceNodeRef, NodeRef destinationNodeRef)
{
UpdateResult result = new UpdateResult();
result.setStatement(cmd);
if (sourceNodeRef != null)
{
result.setSource(Utils.convertToReference(sourceNodeRef));
}
if (destinationNodeRef != null)
{
result.setDestination(Utils.convertToReference(destinationNodeRef));
}
// Sort out the count ???
return result;
}
/**
*
* @param addAspect
* @param result
*/
private void executeCMLAddAspect(CMLAddAspect addAspect, ExecutionContext context, List<UpdateResult> results)
{
// Get the node refs
List<NodeRef> nodeRefs = getNodeRefList(addAspect.getWhere_id(), addAspect.getWhere(), context);
// Get the aspect name and the properties
QName aspectQName = QName.createQName(addAspect.getAspect());
PropertyMap properties = getPropertyMap(addAspect.getProperty());
for (NodeRef nodeRef : nodeRefs)
{
// Add the aspect
this.nodeService.addAspect(nodeRef, aspectQName, properties);
// Create the result
results.add(createResult(ADD_ASPECT, nodeRef, nodeRef));
}
}
private void executeCMLRemoveAspect(CMLRemoveAspect removeAspect, ExecutionContext context, List<UpdateResult> results)
{
// Get the node refs
List<NodeRef> nodeRefs = getNodeRefList(removeAspect.getWhere_id(), removeAspect.getWhere(), context);
// Get the aspect name
QName aspectQName = QName.createQName(removeAspect.getAspect());
for (NodeRef nodeRef : nodeRefs)
{
// Add the aspect
this.nodeService.removeAspect(nodeRef, aspectQName);
// Create the result
results.add(createResult(REMOVE_ASPECT, nodeRef, nodeRef));
}
}
private List<NodeRef> getNodeRefList(String id, Predicate predicate, ExecutionContext context)
{
List<NodeRef> nodeRefs = new ArrayList<NodeRef>();
if (id != null && id.length() != 0)
{
NodeRef localNodeRef = context.getNodeRef(id);
if (localNodeRef != null)
{
nodeRefs.add(localNodeRef);
}
}
else
{
nodeRefs = Utils.resolvePredicate(predicate, this.nodeService, this.searchService, this.namespaceService);
}
return nodeRefs;
}
private void executeCMLUpdate(CMLUpdate update, ExecutionContext context, List<UpdateResult> results)
{
// Get the nodes and properties
List<NodeRef> nodeRefs = getNodeRefList(update.getWhere_id(), update.getWhere(), context);
PropertyMap props = getPropertyMap(update.getProperty());
for (NodeRef nodeRef : nodeRefs)
{
// Update the property values
Map<QName, Serializable> currentProps = this.nodeService.getProperties(nodeRef);
currentProps.putAll(props);
this.nodeService.setProperties(nodeRef, currentProps);
// Get the result
results.add(createResult(UPDATE, nodeRef, nodeRef));
}
}
private void executeCMLDelete(CMLDelete delete, ExecutionContext context, List<UpdateResult> results)
{
List<NodeRef> nodeRefs = Utils.resolvePredicate(delete.getWhere(), this.nodeService, this.searchService, this.namespaceService);
for (NodeRef nodeRef : nodeRefs)
{
// Delete the node
this.nodeService.deleteNode(nodeRef);
// Create the result
results.add(createResult(DELETE, nodeRef, null));
}
}
private void executeCMLMove(CMLMove move, ExecutionContext context, List<UpdateResult> results)
{
NodeRef destinationNodeRef = getNodeRef(move.getTo_id(), move.getTo(), context);
if (destinationNodeRef != null)
{
QName assocType = null;
QName assocName = null;
if (move.getTo_id() != null)
{
assocType = QName.createQName(move.getAssociationType());
assocName = QName.createQName(move.getChildName());
}
else
{
assocType = QName.createQName(move.getTo().getAssociationType());
assocName = QName.createQName(move.getTo().getChildName());
}
List<NodeRef> nodesToMove = getNodeRefList(move.getWhere_id(), move.getWhere(), context);
for (NodeRef nodeToMove : nodesToMove)
{
NodeRef newNodeRef = this.nodeService.moveNode(nodeToMove, destinationNodeRef, assocType, assocName).getChildRef();
// Create the result
results.add(createResult(MOVE, nodeToMove, newNodeRef));
}
}
}
private NodeRef getNodeRef(String id, ParentReference parentReference, ExecutionContext context)
{
NodeRef nodeRef = null;
if (id != null && id.length() != 0)
{
nodeRef = context.getNodeRef(id);
}
else
{
nodeRef = Utils.convertToNodeRef(parentReference, this.nodeService, this.searchService, this.namespaceService);
}
return nodeRef;
}
private NodeRef getNodeRef(String id, Reference reference, ExecutionContext context)
{
NodeRef nodeRef = null;
if (id != null && id.length() != 0)
{
nodeRef = context.getNodeRef(id);
}
else
{
nodeRef = Utils.convertToNodeRef(reference, this.nodeService, this.searchService, this.namespaceService);
}
return nodeRef;
}
private void executeCMLCopy(CMLCopy copy, ExecutionContext context, List<UpdateResult> results)
{
NodeRef destinationNodeRef = getNodeRef(copy.getTo_id(), copy.getTo(), context);
if (destinationNodeRef != null)
{
QName assocType = null;
QName assocName = null;
if (copy.getTo_id() != null)
{
assocType = QName.createQName(copy.getAssociationType());
assocName = QName.createQName(copy.getChildName());
}
else
{
assocType = QName.createQName(copy.getTo().getAssociationType());
assocName = QName.createQName(copy.getTo().getChildName());
}
boolean copyChildren = false;
Boolean value = copy.getChildren();
if (value != null)
{
copyChildren = value.booleanValue();
}
List<NodeRef> nodesToCopy = getNodeRefList(copy.getWhere_id(), copy.getWhere(), context);
for (NodeRef nodeToCopy : nodesToCopy)
{
NodeRef newNodeRef = this.copyService.copy(nodeToCopy, destinationNodeRef, assocType, assocName, copyChildren);
// Create the result
results.add(createResult(COPY, nodeToCopy, newNodeRef));
}
}
}
private void executeCMLAddChild(CMLAddChild addChild, ExecutionContext context, List<UpdateResult> results)
{
NodeRef nodeRef = getNodeRef(addChild.getTo_id(), addChild.getTo(), context);
if (nodeRef != null)
{
QName assocType = null;
QName assocName = null;
if (addChild.getTo_id() != null)
{
assocType = QName.createQName(addChild.getAssociationType());
assocName = QName.createQName(addChild.getChildName());
}
else
{
assocType = QName.createQName(addChild.getTo().getAssociationType());
assocName = QName.createQName(addChild.getTo().getChildName());
}
List<NodeRef> whereNodeRefs = getNodeRefList(addChild.getWhere_id(), addChild.getWhere(), context);
for (NodeRef whereNodeRef : whereNodeRefs)
{
this.nodeService.addChild(nodeRef, whereNodeRef, assocType, assocName);
// Create the result
results.add(createResult(ADD_CHILD, nodeRef, whereNodeRef));
}
}
}
private void executeCMLRemoveChild(CMLRemoveChild removeChild, ExecutionContext context, List<UpdateResult> results)
{
NodeRef parentNodeRef = getNodeRef(removeChild.getFrom_id(), removeChild.getFrom(), context);
if (parentNodeRef != null)
{
List<NodeRef> childNodeRefs = getNodeRefList(removeChild.getWhere_id(), removeChild.getWhere(), context);
for (NodeRef childNodeRef : childNodeRefs)
{
this.nodeService.removeChild(parentNodeRef, childNodeRef);
// Create the result
results.add(createResult(REMOVE_CHILD, parentNodeRef, null));
}
}
}
private void executeCMLCreateAssociation(CMLCreateAssociation createAssoc, ExecutionContext context, List<UpdateResult> results)
{
QName assocType = QName.createQName(createAssoc.getAssociation());
if (assocType != null)
{
List<NodeRef> fromNodeRefs = getNodeRefList(createAssoc.getFrom_id(), createAssoc.getFrom(), context);
List<NodeRef> toNodeRefs = getNodeRefList(createAssoc.getTo_id(), createAssoc.getTo(), context);
for (NodeRef fromNodeRef : fromNodeRefs)
{
for (NodeRef toNodeRef : toNodeRefs)
{
this.nodeService.createAssociation(fromNodeRef, toNodeRef, assocType);
// Create the result
results.add(createResult(CREATE_ASSOCIATION, fromNodeRef, toNodeRef));
}
}
}
}
private void executeCMLRemoveAssociation(CMLRemoveAssociation removeAssoc, ExecutionContext context, List<UpdateResult> results)
{
QName assocType = QName.createQName(removeAssoc.getAssociation());
if (assocType != null)
{
List<NodeRef> fromNodeRefs = getNodeRefList(removeAssoc.getFrom_id(), removeAssoc.getFrom(), context);
List<NodeRef> toNodeRefs = getNodeRefList(removeAssoc.getTo_id(), removeAssoc.getTo(), context);
for (NodeRef fromNodeRef : fromNodeRefs)
{
for (NodeRef toNodeRef : toNodeRefs)
{
this.nodeService.removeAssociation(fromNodeRef, toNodeRef, assocType);
// Create the result
results.add(createResult(REMOVE_ASSOCIATION, fromNodeRef, toNodeRef));
}
}
}
}
private class ExecutionContext
{
private Map<String, NodeRef> idMap = new HashMap<String, NodeRef>();
public void addId(String id, NodeRef nodeRef)
{
this.idMap.put(id, nodeRef);
}
public NodeRef getNodeRef(String id)
{
return this.idMap.get(id);
}
}
}

View File

@@ -0,0 +1,448 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice;
import java.util.List;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.webservice.repository.UpdateResult;
import org.alfresco.repo.webservice.types.CML;
import org.alfresco.repo.webservice.types.CMLAddAspect;
import org.alfresco.repo.webservice.types.CMLAddChild;
import org.alfresco.repo.webservice.types.CMLCopy;
import org.alfresco.repo.webservice.types.CMLCreate;
import org.alfresco.repo.webservice.types.CMLCreateAssociation;
import org.alfresco.repo.webservice.types.CMLDelete;
import org.alfresco.repo.webservice.types.CMLMove;
import org.alfresco.repo.webservice.types.CMLRemoveAspect;
import org.alfresco.repo.webservice.types.CMLRemoveAssociation;
import org.alfresco.repo.webservice.types.CMLRemoveChild;
import org.alfresco.repo.webservice.types.CMLUpdate;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.ParentReference;
import org.alfresco.repo.webservice.types.Predicate;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
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.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.BaseSpringTest;
import org.alfresco.util.PropertyMap;
/**
* @author Roy Wetherall
*/
public class CMLUtilTest extends BaseSpringTest
{
private static final ContentData CONTENT_DATA_TEXT_UTF8 = new ContentData(null, MimetypeMap.MIMETYPE_TEXT_PLAIN, 0L, "UTF-8");
private static final ContentData CONTENT_DATA_HTML_UTF16 = new ContentData(null, MimetypeMap.MIMETYPE_HTML, 0L, "UTF-16");
private CMLUtil cmlUtil;
private NodeService nodeService;
private StoreRef testStoreRef;
private NodeRef rootNodeRef;
private NodeRef nodeRef;
private NamespaceService namespaceService;
private SearchService searchService;
private NodeRef folderNodeRef;
private AuthenticationComponent authenticationComponent;
@Override
protected String[] getConfigLocations()
{
return new String[]{"classpath:org/alfresco/repo/webservice/cml-test.xml"};
}
@Override
protected void onSetUpInTransaction() throws Exception
{
this.cmlUtil = (CMLUtil)this.applicationContext.getBean("CMLUtil");
this.nodeService = (NodeService)this.applicationContext.getBean("nodeService");
this.searchService = (SearchService)this.applicationContext.getBean("searchService");
this.namespaceService = (NamespaceService)this.applicationContext.getBean("namespaceService");
this.authenticationComponent = (AuthenticationComponent) this.applicationContext.getBean("authenticationComponent");
this.authenticationComponent.setSystemUserAsCurrentUser();
// Create the store and get the root node
this.testStoreRef = this.nodeService.createStore(
StoreRef.PROTOCOL_WORKSPACE, "Test_"
+ System.currentTimeMillis());
this.rootNodeRef = this.nodeService.getRootNode(this.testStoreRef);
// Create the node used for tests
PropertyMap contentProps = new PropertyMap();
contentProps.put(ContentModel.PROP_CONTENT, CONTENT_DATA_TEXT_UTF8);
this.nodeRef = this.nodeService.createNode(
this.rootNodeRef,
ContentModel.ASSOC_CHILDREN,
ContentModel.ASSOC_CHILDREN,
ContentModel.TYPE_CONTENT,
contentProps).getChildRef();
this.folderNodeRef = this.nodeService.createNode(
this.rootNodeRef,
ContentModel.ASSOC_CHILDREN,
ContentModel.ASSOC_CHILDREN,
ContentModel.TYPE_FOLDER).getChildRef();
}
@Override
protected void onTearDownInTransaction()
{
authenticationComponent.clearCurrentSecurityContext();
super.onTearDownInTransaction();
}
public void testMoreThanOneStatement()
{
}
public void testCreate()
{
CMLCreate[] creates = new CMLCreate[]{createCMLCreate(ContentModel.TYPE_CONTENT, "id1")};
CML cml = new CML();
cml.setCreate(creates);
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("create", updateResult.getStatement());
assertNull(updateResult.getSource());
assertNotNull(updateResult.getDestination());
NodeRef createdNodeRef = Utils.convertToNodeRef(updateResult.getDestination(), this.nodeService, this.searchService, this.namespaceService);
assertNotNull(createdNodeRef);
assertEquals(ContentModel.TYPE_CONTENT, this.nodeService.getType(createdNodeRef));
assertEquals("name", this.nodeService.getProperty(createdNodeRef, ContentModel.PROP_NAME));
//System.out.println(NodeStoreInspector.dumpNodeStore(this.nodeService, this.testStoreRef));
}
public void testAddRemoveAspect()
{
CMLAddAspect addAspect = new CMLAddAspect();
addAspect.setAspect(ContentModel.ASPECT_VERSIONABLE.toString());
addAspect.setWhere(createPredicate(this.nodeRef));
CML cml = new CML();
cml.setAddAspect(new CMLAddAspect[]{addAspect});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("addAspect", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNotNull(updateResult.getDestination());
assertTrue(this.nodeService.hasAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE));
// TODO should test with properties set as well
CMLRemoveAspect removeAspect = new CMLRemoveAspect();
removeAspect.setAspect(ContentModel.ASPECT_VERSIONABLE.toString());
removeAspect.setWhere(createPredicate(this.nodeRef));
CML cml2 = new CML();
cml2.setRemoveAspect(new CMLRemoveAspect[]{removeAspect});
UpdateResult[] results2 = this.cmlUtil.executeCML(cml2);
assertNotNull(results2);
assertEquals(1, results2.length);
UpdateResult result2 = results2[0];
assertEquals("removeAspect", result2.getStatement());
assertNotNull(result2.getDestination());
assertNotNull(result2.getSource());
assertFalse(this.nodeService.hasAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE));
}
public void testUpdate()
{
CMLUpdate update = new CMLUpdate();
update.setWhere(createPredicate(this.nodeRef));
update.setProperty(new NamedValue[]
{
new NamedValue(ContentModel.PROP_NAME.toString(), "updatedName"),
new NamedValue(ContentModel.PROP_CONTENT.toString(), CONTENT_DATA_HTML_UTF16.toString())
});
CML cml = new CML();
cml.setUpdate(new CMLUpdate[]{update});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("update", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNotNull(updateResult.getDestination());
assertEquals("updatedName", this.nodeService.getProperty(this.nodeRef, ContentModel.PROP_NAME));
assertEquals(CONTENT_DATA_HTML_UTF16, this.nodeService.getProperty(this.nodeRef, ContentModel.PROP_CONTENT));
}
public void testDelete()
{
CMLDelete delete = new CMLDelete();
delete.setWhere(createPredicate(this.nodeRef));
CML cml = new CML();
cml.setDelete(new CMLDelete[]{delete});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("delete", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNull(updateResult.getDestination());
// Check that the node no longer exists
assertFalse(this.nodeService.exists(this.nodeRef));
}
public void testMove()
{
CMLMove move = new CMLMove();
move.setTo(createParentReference(this.folderNodeRef, ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS));
move.setWhere(createPredicate(this.nodeRef));
CML cml = new CML();
cml.setMove(new CMLMove[]{move});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("move", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNotNull(updateResult.getDestination());
List<ChildAssociationRef> assocs = this.nodeService.getChildAssocs(this.folderNodeRef);
assertNotNull(assocs);
assertEquals(1, assocs.size());
ChildAssociationRef assoc = assocs.get(0);
assertEquals(assoc.getChildRef(), Utils.convertToNodeRef(
updateResult.getDestination(),
this.nodeService,
this.searchService,
this.namespaceService));
}
public void testCopy()
{
CMLCopy copy = new CMLCopy();
copy.setTo(createParentReference(this.folderNodeRef, ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS));
copy.setWhere(createPredicate(this.nodeRef));
CML cml = new CML();
cml.setCopy(new CMLCopy[]{copy});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("copy", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNotNull(updateResult.getDestination());
List<ChildAssociationRef> assocs = this.nodeService.getChildAssocs(this.folderNodeRef);
assertNotNull(assocs);
assertEquals(1, assocs.size());
ChildAssociationRef assoc = assocs.get(0);
assertEquals(assoc.getChildRef(), Utils.convertToNodeRef(
updateResult.getDestination(),
this.nodeService,
this.searchService,
this.namespaceService));
}
public void testAddChild()
{
CMLAddChild addChild = new CMLAddChild();
addChild.setTo(createParentReference(this.folderNodeRef, ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS));
addChild.setWhere(createPredicate(this.nodeRef));
CML cml = new CML();
cml.setAddChild(new CMLAddChild[]{addChild});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("addChild", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNotNull(updateResult.getDestination());
List<ChildAssociationRef> assocs = this.nodeService.getChildAssocs(this.folderNodeRef);
assertNotNull(assocs);
assertEquals(1, assocs.size());
ChildAssociationRef assoc = assocs.get(0);
assertEquals(assoc.getChildRef(), Utils.convertToNodeRef(
updateResult.getDestination(),
this.nodeService,
this.searchService,
this.namespaceService));
}
public void testRemoveChild()
{
// Add the node as a child of the folder
this.nodeService.addChild(this.folderNodeRef, this.nodeRef, ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS);
CMLRemoveChild removeChild = new CMLRemoveChild();
removeChild.setFrom(Utils.convertToReference(this.folderNodeRef));
removeChild.setWhere(createPredicate(this.nodeRef));
CML cml = new CML();
cml.setRemoveChild(new CMLRemoveChild[]{removeChild});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("removeChild", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNull(updateResult.getDestination());
List<ChildAssociationRef> assocs = this.nodeService.getChildAssocs(this.folderNodeRef);
assertEquals(0, assocs.size());
}
public void testCreateAssociation()
{
CMLCreateAssociation createAssoc = new CMLCreateAssociation();
createAssoc.setAssociation(ContentModel.ASSOC_CONTAINS.toString());
createAssoc.setFrom(createPredicate(this.folderNodeRef));
createAssoc.setTo(createPredicate(this.nodeRef));
CML cml = new CML();
cml.setCreateAssociation(new CMLCreateAssociation[]{createAssoc});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("createAssociation", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNotNull(updateResult.getDestination());
List<AssociationRef> assocs = this.nodeService.getTargetAssocs(this.folderNodeRef, ContentModel.ASSOC_CONTAINS);
assertNotNull(assocs);
assertEquals(1, assocs.size());
AssociationRef assoc = assocs.get(0);
assertEquals(assoc.getTargetRef(), Utils.convertToNodeRef(
updateResult.getDestination(),
this.nodeService,
this.searchService,
this.namespaceService));
}
public void testRemoveAssociation()
{
this.nodeService.createAssociation(this.folderNodeRef, this.nodeRef, ContentModel.ASSOC_CONTAINS);
CMLRemoveAssociation removeAssociation = new CMLRemoveAssociation();
removeAssociation.setAssociation(ContentModel.ASSOC_CONTAINS.toString());
removeAssociation.setFrom(createPredicate(this.folderNodeRef));
removeAssociation.setTo(createPredicate(this.nodeRef));
CML cml = new CML();
cml.setRemoveAssociation(new CMLRemoveAssociation[]{removeAssociation});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("removeAssociation", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNotNull(updateResult.getDestination());
List<AssociationRef> assocs = this.nodeService.getTargetAssocs(this.folderNodeRef, ContentModel.ASSOC_CONTAINS);
assertNotNull(assocs);
assertEquals(0, assocs.size());
}
private ParentReference createParentReference(NodeRef nodeRef, QName assocType, QName assocName)
{
ParentReference parentReference = new ParentReference();
parentReference.setAssociationType(assocType.toString());
parentReference.setChildName(assocName.toString());
parentReference.setStore(Utils.convertToStore(nodeRef.getStoreRef()));
parentReference.setUuid(nodeRef.getId());
return parentReference;
}
private Predicate createPredicate(NodeRef nodeRef)
{
Predicate predicate = new Predicate();
predicate.setStore(Utils.convertToStore(nodeRef.getStoreRef()));
predicate.setNodes(new Reference[]{Utils.convertToReference(nodeRef)});
return predicate;
}
private CMLCreate createCMLCreate(QName type, String id)
{
CMLCreate create = new CMLCreate();
create.setId("id1");
create.setType(ContentModel.TYPE_CONTENT.toString());
ParentReference parentReference = new ParentReference();
parentReference.setAssociationType(ContentModel.ASSOC_CHILDREN.toString());
parentReference.setChildName(ContentModel.ASSOC_CHILDREN.toString());
parentReference.setStore(Utils.convertToStore(this.testStoreRef));
parentReference.setUuid(this.rootNodeRef.getId());
create.setParent(parentReference);
create.setProperty(getContentNamedValues());
return create;
}
private NamedValue[] getContentNamedValues()
{
return new NamedValue[]
{
new NamedValue(ContentModel.PROP_NAME.toString(), "name"),
new NamedValue(ContentModel.PROP_CONTENT.toString(), CONTENT_DATA_TEXT_UTF8.toString())
};
}
}

View File

@@ -0,0 +1,600 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.transaction.UserTransaction;
import org.alfresco.repo.webservice.axis.QueryConfigHandler;
import org.alfresco.repo.webservice.types.AssociationDefinition;
import org.alfresco.repo.webservice.types.Cardinality;
import org.alfresco.repo.webservice.types.ClassDefinition;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.ParentReference;
import org.alfresco.repo.webservice.types.Predicate;
import org.alfresco.repo.webservice.types.PropertyDefinition;
import org.alfresco.repo.webservice.types.Query;
import org.alfresco.repo.webservice.types.QueryLanguageEnum;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.repo.webservice.types.RoleDefinition;
import org.alfresco.repo.webservice.types.Store;
import org.alfresco.repo.webservice.types.StoreEnum;
import org.alfresco.repo.webservice.types.Version;
import org.alfresco.service.ServiceRegistry;
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.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.apache.axis.MessageContext;
import org.apache.axis.transport.http.HTTPConstants;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* Helper class used by the web services
*
* @author gavinc
*/
public class Utils
{
public static final String REPOSITORY_SERVICE_NAMESPACE = "http://www.alfresco.org/ws/service/repository/1.0";
private Utils()
{
// don't allow construction
}
/**
* Converts the web service Store type to a StoreRef used by the repository
*
* @param store
* The Store to convert
* @return The converted StoreRef
*/
public static StoreRef convertToStoreRef(Store store)
{
return new StoreRef(store.getScheme().getValue(), store.getAddress());
}
/**
* Converts a store reference ot a Store type
*
* @param ref
* the store reference
* @return the store
*/
public static Store convertToStore(StoreRef ref)
{
return new Store(StoreEnum.fromValue(ref.getProtocol()), ref
.getIdentifier());
}
/**
* Converts the given Reference web service type into a repository NodeRef
*
* @param ref
* The Reference to convert
* @return The NodeRef representation of the Reference
*/
public static NodeRef convertToNodeRef(Reference ref,
NodeService nodeService, SearchService searchService,
NamespaceService namespaceService)
{
return resolveToNodeRef(ref.getStore(), ref.getUuid(), ref.getPath(),
nodeService, searchService, namespaceService);
}
/**
* Converts the given ParentReference web service type into a repository
* NodeRef
*
* @param parentRef
* The ParentReference to convert
* @return The NodeRef representation of the ParentReference
*/
public static NodeRef convertToNodeRef(ParentReference parentRef,
NodeService nodeService, SearchService searchService,
NamespaceService namespaceService)
{
// TODO: Also take into account any association information passed in
// the ParentReference
return resolveToNodeRef(parentRef.getStore(), parentRef.getUuid(),
parentRef.getPath(), nodeService, searchService,
namespaceService);
}
/**
* Converts the given repository NodeRef object into a web service Reference
* type
*
* @param node
* The node to create a Reference for
* @return The Reference
*/
public static Reference convertToReference(NodeRef node)
{
Reference ref = new Reference();
Store store = new Store(StoreEnum.fromValue(node.getStoreRef()
.getProtocol()), node.getStoreRef().getIdentifier());
ref.setStore(store);
ref.setUuid(node.getId());
return ref;
}
/**
* Resolves the given parameters to a repository NodeRef
*
* @param store
* The Store to search within
* @param uuid
* The id of the node, or the id of the starting node if a path
* is also present
* @param path
* The path to the required node, if a uuid is given the search
* starts from that node otherwise the search will start from the
* root node
* @param nodeService
* NodeService to use
* @param searchService
* SearchService to use
* @param namespaceService
* NamespaceService to use
* @return A repository NodeRef
*/
public static NodeRef resolveToNodeRef(Store store, String uuid,
String path, NodeService nodeService, SearchService searchService,
NamespaceService namespaceService)
{
if (store == null)
{
throw new IllegalArgumentException(
"A Store must be supplied to resolve to a NodeRef");
}
NodeRef nodeRef = null;
// find out where we are starting from, either the root or the node
// represented by the uuid
NodeRef rootNodeRef = null;
if (uuid == null)
{
rootNodeRef = nodeService.getRootNode(convertToStoreRef(store));
} else
{
rootNodeRef = new NodeRef(convertToStoreRef(store), uuid);
}
// see if we have a path to further define the node being requested
if (path != null)
{
List<NodeRef> nodes = searchService.selectNodes(rootNodeRef, path,
null, namespaceService, false);
// make sure we only have one result
if (nodes.size() != 1)
{
StringBuilder builder = new StringBuilder(
"Failed to resolve to a single NodeRef with parameters (store=");
builder.append(store.getScheme().getValue()).append(":")
.append(store.getAddress());
builder.append(" uuid=").append(uuid);
builder.append(" path=").append(path).append("), found ");
builder.append(nodes.size()).append(" nodes.");
throw new IllegalStateException(builder.toString());
}
nodeRef = nodes.get(0);
} else
{
// if there is no path just use whatever the rootNodeRef currently
// is
nodeRef = rootNodeRef;
}
return nodeRef;
}
/**
* Resolves the given predicate into a list of NodeRefs that can be acted
* upon
*
* @param predicate
* The predicate passed from the client
* @param nodeService
* NodeService to use
* @param searchService
* SearchService to use
* @param namespaceService
* NamespaceService to use
* @return A List of NodeRef objects
*/
public static List<NodeRef> resolvePredicate(Predicate predicate,
NodeService nodeService, SearchService searchService,
NamespaceService namespaceService)
{
List<NodeRef> nodeRefs = null;
if (predicate.getNodes() != null)
{
Reference[] nodes = predicate.getNodes();
nodeRefs = new ArrayList<NodeRef>(nodes.length);
for (int x = 0; x < nodes.length; x++)
{
nodeRefs.add(convertToNodeRef(nodes[x], nodeService,
searchService, namespaceService));
}
}
else if (predicate.getQuery() != null)
{
// make sure a query is present
Query query = predicate.getQuery();
if (query == null)
{
throw new IllegalStateException(
"Either a set of nodes or a query must be supplied in a Predicate.");
}
// make sure a Store has been supplied too
if (predicate.getStore() == null)
{
throw new IllegalStateException(
"A Store has to be supplied to in order to execute a query.");
}
QueryLanguageEnum langEnum = query.getLanguage();
if (langEnum.equals(QueryLanguageEnum.cql)
|| langEnum.equals(QueryLanguageEnum.xpath))
{
throw new IllegalArgumentException("Only '"
+ QueryLanguageEnum.lucene.getValue()
+ "' queries are currently supported!");
}
// execute the query
ResultSet searchResults = null;
try
{
searchResults = searchService.query(Utils
.convertToStoreRef(predicate.getStore()), langEnum
.getValue(), query.getStatement());
// get hold of all the NodeRef's from the results
nodeRefs = searchResults.getNodeRefs();
}
finally
{
if (searchResults != null)
{
searchResults.close();
}
}
}
else if (predicate.getStore() != null)
{
// Since only the store was supplied interpret this to mean the predicate should be resolved to the
// stores root node
Store store = predicate.getStore();
NodeRef rootNode = nodeService.getRootNode(Utils.convertToStoreRef(store));
nodeRefs = new ArrayList<NodeRef>();
nodeRefs.add(rootNode);
}
return nodeRefs;
}
/**
* Returns the current Spring WebApplicationContext object
*
* @param msgContext
* SOAP message context
* @return The Spring WebApplicationContext
*/
public static WebApplicationContext getSpringContext(
MessageContext msgContext)
{
// get hold of the web application context via the message context
HttpServletRequest req = (HttpServletRequest) msgContext
.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
ServletContext servletCtx = req.getSession().getServletContext();
return WebApplicationContextUtils
.getRequiredWebApplicationContext(servletCtx);
}
/**
* Returns a UserTransaction that can be used within a service call
*
* @param msgContext
* SOAP message context
* @return a UserTransaction
*/
public static UserTransaction getUserTransaction(MessageContext msgContext)
{
// get the service regsistry
ServiceRegistry svcReg = (ServiceRegistry) getSpringContext(msgContext)
.getBean(ServiceRegistry.SERVICE_REGISTRY);
TransactionService transactionService = svcReg.getTransactionService();
return transactionService.getUserTransaction();
}
/**
* Returns the value of the <code>fetchSize</code> from the
* QueryConfiguration SOAP header (if present)
*
* @param msgContext
* The SOAP MessageContext
* @return The current batch size or -1 if the header is not present
*/
public static int getBatchSize(MessageContext msgContext)
{
int batchSize = -1;
Integer batchConfigSize = (Integer) MessageContext.getCurrentContext()
.getProperty(QueryConfigHandler.ALF_FETCH_SIZE);
if (batchConfigSize != null)
{
batchSize = batchConfigSize.intValue();
}
return batchSize;
}
/**
* Converts a repository version object into a web service version object.
*
* @param version
* the repository version object
* @return the web service version object
*/
public static Version convertToVersion(
org.alfresco.service.cmr.version.Version version)
{
Version webServiceVersion = new Version();
// Set the basic properties
webServiceVersion.setId(Utils.convertToReference(version
.getFrozenStateNodeRef()));
webServiceVersion.setCreator(version.getCreator());
webServiceVersion.setLabel(version.getVersionLabel());
// Set the created date
Date createdDate = version.getCreatedDate();
Calendar calendar = Calendar.getInstance();
calendar.setTime(createdDate);
webServiceVersion.setCreated(calendar);
// Set the falg to indicate whether the version was mojor or minor
boolean isMajor = false;
VersionType versionType = version.getVersionType();
if (versionType != null
&& versionType.equals(VersionType.MAJOR) == true)
{
isMajor = true;
}
webServiceVersion.setMajor(isMajor);
// Set the commetary values
Map<String, Serializable> versionProps = version.getVersionProperties();
NamedValue[] namedValues = new NamedValue[versionProps.size()];
int iIndex = 0;
for (Map.Entry<String, Serializable> entry : versionProps.entrySet())
{
String value = null;
try
{
value = DefaultTypeConverter.INSTANCE.convert(String.class, entry.getValue());
}
catch (Throwable exception)
{
value = entry.getValue().toString();
}
namedValues[iIndex] = new NamedValue(entry.getKey(), value);
iIndex++;
}
webServiceVersion.setCommentaries(namedValues);
return webServiceVersion;
}
/**
* Creates a ClassDefinition web service type object for the given
* repository ClassDefinition
*
* @param ddClassDef The repository ClassDefinition to generate
* @return The web service ClassDefinition representation
*/
public static ClassDefinition setupClassDefObject(org.alfresco.service.cmr.dictionary.ClassDefinition ddClassDef)
{
ClassDefinition classDef = new ClassDefinition();
classDef.setName(ddClassDef.getName().toString());
classDef.setIsAspect(ddClassDef.isAspect());
if (ddClassDef.getTitle() != null)
{
classDef.setTitle(ddClassDef.getTitle());
}
if (ddClassDef.getDescription() != null)
{
classDef.setDescription(ddClassDef.getDescription());
}
if (ddClassDef.getParentName() != null)
{
classDef.setSuperClass(ddClassDef.getParentName().toString());
}
// represent the properties
Map<QName, org.alfresco.service.cmr.dictionary.PropertyDefinition> props = ddClassDef.getProperties();
if (props != null)
{
PropertyDefinition[] propDefs = new PropertyDefinition[props.size()];
int pos = 0;
for (org.alfresco.service.cmr.dictionary.PropertyDefinition ddPropDef : props.values())
{
PropertyDefinition propDef = new PropertyDefinition();
propDef.setName(ddPropDef.getName().toString());
propDef.setDataType(ddPropDef.getDataType().getName().toString());
propDef.setMandatory(ddPropDef.isMandatory());
propDef.setReadOnly(ddPropDef.isProtected());
if (ddPropDef.getDefaultValue() != null)
{
propDef.setDefaultValue(ddPropDef.getDefaultValue());
}
if (ddPropDef.getTitle() != null)
{
propDef.setTitle(ddPropDef.getTitle());
}
if (ddPropDef.getDescription() != null)
{
propDef.setDescription(ddPropDef.getDescription());
}
// add it to the array
propDefs[pos] = propDef;
pos++;
}
// add properties to the overall ClassDefinition
classDef.setProperties(propDefs);
}
// TODO need to get the child associations as well !!
// represent the associations
Map<QName, org.alfresco.service.cmr.dictionary.AssociationDefinition> assocs = ddClassDef.getAssociations();
if (assocs != null)
{
AssociationDefinition[] assocDefs = new AssociationDefinition[assocs.size()];
int pos = 0;
for (org.alfresco.service.cmr.dictionary.AssociationDefinition ddAssocDef : assocs.values())
{
AssociationDefinition assocDef = new AssociationDefinition();
assocDef.setName(ddAssocDef.getName().toString());
assocDef.setIsChild(ddAssocDef.isChild());
if (ddAssocDef.getTitle() != null)
{
assocDef.setTitle(ddAssocDef.getTitle());
}
if (ddAssocDef.getDescription() != null)
{
assocDef.setDescription(ddAssocDef.getDescription());
}
RoleDefinition sourceRole = new RoleDefinition();
if (ddAssocDef.getSourceRoleName() != null)
{
sourceRole.setName(ddAssocDef.getSourceRoleName().toString());
}
sourceRole.setCardinality(setupSourceCardinalityObject(ddAssocDef));
assocDef.setSourceRole(sourceRole);
RoleDefinition targetRole = new RoleDefinition();
if (ddAssocDef.getTargetRoleName() != null)
{
targetRole.setName(ddAssocDef.getTargetRoleName().toString());
}
targetRole.setCardinality(setupTargetCardinalityObject(ddAssocDef));;
assocDef.setTargetRole(targetRole);
assocDef.setTargetClass(ddAssocDef.getTargetClass().getName().toString());
assocDefs[pos] = assocDef;
pos++;
}
classDef.setAssociations(assocDefs);
}
return classDef;
}
/**
* Creates a web service Cardinality type for the source from the given repository AssociationDefinition
*
* @param ddAssocDef The AssociationDefinition to get the cardinality from
* @return The Cardinality
*/
private static Cardinality setupSourceCardinalityObject(org.alfresco.service.cmr.dictionary.AssociationDefinition ddAssocDef)
{
if (ddAssocDef.isSourceMandatory() == false && ddAssocDef.isSourceMany() == false)
{
// 0..1
return Cardinality.value1;
}
else if (ddAssocDef.isSourceMandatory() && ddAssocDef.isSourceMany() == false)
{
// 1
return Cardinality.value2;
}
else if (ddAssocDef.isSourceMandatory() && ddAssocDef.isSourceMany())
{
// 1..*
return Cardinality.value4;
}
else
{
// *
return Cardinality.value3;
}
}
/**
* Creates a web service Cardinality type for the target from the given repository AssociationDefinition
*
* @param ddAssocDef The AssociationDefinition to get the cardinality from
* @return The Cardinality
*/
private static Cardinality setupTargetCardinalityObject(org.alfresco.service.cmr.dictionary.AssociationDefinition ddAssocDef)
{
if (ddAssocDef.isTargetMandatory() == false && ddAssocDef.isTargetMany() == false)
{
// 0..1
return Cardinality.value1;
}
else if (ddAssocDef.isTargetMandatory() && ddAssocDef.isTargetMany() == false)
{
// 1
return Cardinality.value2;
}
else if (ddAssocDef.isTargetMandatory() && ddAssocDef.isTargetMany())
{
// 1..*
return Cardinality.value4;
}
else
{
// *
return Cardinality.value3;
}
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.authentication;
import java.rmi.RemoteException;
import org.alfresco.example.webservice.TicketHolder;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Web service implementation of the AuthenticationService. The WSDL for this
* service can be accessed from
* http://localhost:8080/alfresco/wsdl/authentication-service.wsdl
*
* @author gavinc
*/
public class AuthenticationWebService implements AuthenticationServiceSoapPort
{
private static Log logger = LogFactory.getLog(AuthenticationWebService.class);
private AuthenticationService authenticationService;
/**
* Sets the AuthenticationService instance to use
*
* @param authenticationSvc
* The AuthenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationSvc)
{
this.authenticationService = authenticationSvc;
}
/**
* @see org.alfresco.repo.webservice.authentication.AuthenticationServiceSoapPort#startSession(java.lang.String,
* java.lang.String)
*/
public AuthenticationResult startSession(String username, String password)
throws RemoteException, AuthenticationFault
{
try
{
this.authenticationService.authenticate(username, password.toCharArray());
String ticket = this.authenticationService.getCurrentTicket();
if (logger.isDebugEnabled())
{
logger.debug("Issued ticket '" + ticket + "' for '" + username + "'");
}
return new AuthenticationResult(username, ticket);
}
catch (AuthenticationException ae)
{
throw new AuthenticationFault(100, ae.getMessage());
}
catch (Throwable e)
{
throw new AuthenticationFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authentication.AuthenticationServiceSoapPort#endSession()
*/
public void endSession() throws RemoteException, AuthenticationFault
{
try
{
String ticket = TicketHolder.ticket;
if (ticket != null)
{
this.authenticationService.invalidateTicket(ticket);
this.authenticationService.clearCurrentSecurityContext();
if (logger.isDebugEnabled())
{
logger.debug("Session ended for ticket '" + ticket + "'");
}
}
}
catch (Throwable e)
{
throw new AuthenticationFault(0, e.getMessage());
}
}
}

View File

@@ -0,0 +1,804 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.authoring;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.transaction.TransactionUtil;
import org.alfresco.repo.webservice.AbstractWebService;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.ContentFormat;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.ParentReference;
import org.alfresco.repo.webservice.types.Predicate;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.repo.webservice.types.VersionHistory;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.lock.LockType;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Web service implementation of the AuthoringService. The WSDL for this service
* can be accessed from
* http://localhost:8080/alfresco/wsdl/authoring-service.wsdl
*
* @author gavinc
*/
public class AuthoringWebService extends AbstractWebService implements
AuthoringServiceSoapPort
{
/**
* Logger
*/
private static Log logger = LogFactory.getLog(AuthoringWebService.class);
/**
* The check in check out service
*/
private CheckOutCheckInService cociService;
/**
* The lock service
*/
private LockService lockService;
/**
* The version service
*/
private VersionService versionService;
/**
* The transaction service
*/
private TransactionService transactionService;
/**
* Sets the CheckInCheckOutService to use
*
* @param cociService
* The CheckInCheckOutService
*/
public void setCheckOutCheckinService(CheckOutCheckInService cociService)
{
this.cociService = cociService;
}
/**
* Sets the LockService to use
*
* @param lockService the lock service
*/
public void setLockService(LockService lockService)
{
this.lockService = lockService;
}
/**
* Set the version service
*
* @param versionService the version service
*/
public void setVersionService(VersionService versionService)
{
this.versionService = versionService;
}
/**
* Set the transaction service
*
* @param transactionService
* the transaction service
*/
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#checkout(org.alfresco.repo.webservice.types.Predicate,
* org.alfresco.repo.webservice.types.ParentReference)
*/
public CheckoutResult checkout(final Predicate items, final ParentReference destination) throws RemoteException,
AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<CheckoutResult>()
{
public CheckoutResult doWork()
{
List<NodeRef> nodes = Utils.resolvePredicate(items,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
CheckoutResult checkoutResult = new CheckoutResult();
Reference[] originals = new Reference[nodes.size()];
Reference[] workingCopies = new Reference[nodes.size()];
// get a repository NodeRef for the destination (if
// there is one)
NodeRef destinationRef = null;
if (destination != null)
{
destinationRef = Utils.convertToNodeRef(
destination,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
}
for (int x = 0; x < nodes.size(); x++)
{
// get the current node
NodeRef original = nodes.get(x);
// call the appropriate service method depending on
// whether a destination has been provided
NodeRef workingCopy = null;
if (destinationRef != null)
{
workingCopy = AuthoringWebService.this.cociService
.checkout(
original,
destinationRef,
QName.createQName(destination.getAssociationType()),
QName.createQName(destination.getChildName()));
} else
{
workingCopy = AuthoringWebService.this.cociService
.checkout(original);
}
// store the results
originals[x] = Utils.convertToReference(original);
workingCopies[x] = Utils.convertToReference(workingCopy);
}
// setup the result object
checkoutResult.setOriginals(originals);
checkoutResult.setWorkingCopies(workingCopies);
return checkoutResult;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#checkin(org.alfresco.repo.webservice.types.Predicate,
* org.alfresco.repo.webservice.types.NamedValue[], boolean)
*/
public CheckinResult checkin(final Predicate items,
final NamedValue[] comments, final boolean keepCheckedOut)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<CheckinResult>()
{
public CheckinResult doWork()
{
// Get the passed nodes
List<NodeRef> nodes = Utils.resolvePredicate(
items,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
// Map the comments into the expected map
Map<String, Serializable> mapComments = new HashMap<String, Serializable>(comments.length);
for (NamedValue value : comments)
{
mapComments.put(value.getName(), value.getValue());
}
Reference[] checkedIn = new Reference[nodes.size()];
List<Reference> listWorkingCopies = new ArrayList<Reference>(nodes.size());
int iIndex = 0;
// Execute checkin for each node
// TODO should be able to do this as a batch so that all the nodes are versioned together
for (NodeRef node : nodes)
{
// Checkin the node
NodeRef checkedInNode = AuthoringWebService.this.cociService.checkin(node, mapComments, null, keepCheckedOut);
// Add the results to the array
checkedIn[iIndex] = Utils.convertToReference(checkedInNode);
// Only return the working copies if the node is keep checked out otherwise the working copies have been deleted
if (keepCheckedOut == true)
{
listWorkingCopies.add(Utils.convertToReference(node));
}
iIndex++;
}
// Sort out the working copy list
Reference[] workingCopies = listWorkingCopies.toArray(new Reference[listWorkingCopies.size()]);
if (workingCopies == null)
{
workingCopies = new Reference[0];
}
// Create the result object
CheckinResult result = new CheckinResult();
result.setCheckedIn(checkedIn);
result.setWorkingCopies(workingCopies);
return result;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#checkinExternal(org.alfresco.repo.webservice.types.Reference, org.alfresco.repo.webservice.types.NamedValue[], boolean, org.alfresco.repo.webservice.types.ContentFormat, byte[])
*/
public Reference checkinExternal(final Reference node, final NamedValue[] comments, final boolean keepCheckedOut, final ContentFormat format, final byte[] content)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<Reference>()
{
public Reference doWork()
{
// Get the passed nodes
NodeRef nodeRef = Utils.convertToNodeRef(
node,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
// Write the content to the server
// TODO: Need to get the property QName into this method
ContentWriter contentWriter = AuthoringWebService.this.contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, false);
if (contentWriter == null)
{
throw new RuntimeException("Unable to write external content before checkin.");
}
InputStream is = new ByteArrayInputStream(content);
contentWriter.setEncoding(format.getEncoding());
contentWriter.setMimetype(format.getMimetype());
contentWriter.putContent(is);
String contentUrl = contentWriter.getContentUrl();
// Get the version properties map
Map<String, Serializable> versionProperties = new HashMap<String, Serializable>(comments.length);
for (NamedValue namedValue : comments)
{
versionProperties.put(namedValue.getName(), namedValue.getValue());
}
// CheckIn the content
NodeRef origNodeRef = AuthoringWebService.this.cociService.checkin(
nodeRef,
versionProperties,
contentUrl,
keepCheckedOut);
// Return the orig node ref
return Utils.convertToReference(origNodeRef);
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#cancelCheckout(org.alfresco.repo.webservice.types.Predicate)
*/
public CancelCheckoutResult cancelCheckout(final Predicate items)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<CancelCheckoutResult>()
{
public CancelCheckoutResult doWork()
{
// Get the passed nodes
List<NodeRef> nodes = Utils.resolvePredicate(
items,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
// Create the arrays to hold results
Reference[] origNodes = new Reference[nodes.size()];
Reference[] workingCopies = new Reference[nodes.size()];
int iIndex = 0;
for (NodeRef node : nodes)
{
// Cancel the checkout
NodeRef origNode = AuthoringWebService.this.cociService.cancelCheckout(node);
// Set the value in the arrays
origNodes[iIndex] = Utils.convertToReference(origNode);
workingCopies[iIndex] = Utils.convertToReference(node);
iIndex ++;
}
CancelCheckoutResult result = new CancelCheckoutResult();
result.setOriginals(origNodes);
result.setWorkingCopies(workingCopies);
return result;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#lock(org.alfresco.repo.webservice.types.Predicate,
* boolean, org.alfresco.repo.webservice.authoring.LockTypeEnum)
*/
public Reference[] lock(final Predicate items, final boolean lockChildren, final LockTypeEnum lockType)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<Reference[]>()
{
public Reference[] doWork()
{
// Get the passed nodes
List<NodeRef> nodes = Utils.resolvePredicate(
items,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
// Gather together the results
Reference[] result = new Reference[nodes.size()];
int iIndex = 0;
for (NodeRef node : nodes)
{
LockType convertedLockType = convertToLockType(lockType);
AuthoringWebService.this.lockService.lock(node, convertedLockType, 0, lockChildren);
result[iIndex] = Utils.convertToReference(node);
iIndex++;
}
return result;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* Convert from the web service lock type to the Lock type enum value used by the service interface
*
* @param lockTypeEnum web service lock type value
* @return lock type enum value used by the service interface
*/
private LockType convertToLockType(LockTypeEnum lockTypeEnum)
{
LockType lockType = null;
if (lockTypeEnum.equals(LockTypeEnum.write) == true)
{
lockType = LockType.WRITE_LOCK;
}
else
{
lockType = LockType.READ_ONLY_LOCK;
}
return lockType;
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#unlock(org.alfresco.repo.webservice.types.Predicate,
* boolean)
*/
public Reference[] unlock(final Predicate items, final boolean unlockChildren)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<Reference[]>()
{
public Reference[] doWork()
{
// Get the passed nodes
List<NodeRef> nodes = Utils.resolvePredicate(
items,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
// Gather together the results
Reference[] result = new Reference[nodes.size()];
int iIndex = 0;
for (NodeRef node : nodes)
{
AuthoringWebService.this.lockService.unlock(node, unlockChildren);
result[iIndex] = Utils.convertToReference(node);
iIndex++;
}
return result;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#getLockStatus(org.alfresco.repo.webservice.types.Predicate)
*/
public LockStatus[] getLockStatus(final Predicate items)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<LockStatus[]>()
{
public LockStatus[] doWork()
{
// Get the passed nodes
List<NodeRef> nodes = Utils.resolvePredicate(
items,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
// Gather together the results
LockStatus[] result = new LockStatus[nodes.size()];
int iIndex = 0;
for (NodeRef node : nodes)
{
// Get the lock owner
String lockOwner = (String)AuthoringWebService.this.nodeService.getProperty(node, ContentModel.PROP_LOCK_OWNER);
// Get the lock type
LockTypeEnum lockTypeEnum = convertFromLockType(AuthoringWebService.this.lockService.getLockType(node));
LockStatus lockStatus = new LockStatus();
lockStatus.setLockOwner(lockOwner);
lockStatus.setLockType(lockTypeEnum);
lockStatus.setNode(Utils.convertToReference(node));
result[iIndex] = lockStatus;
iIndex++;
}
return result;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
e.printStackTrace();
throw new AuthoringFault(0, e.getMessage());
}
}
private LockTypeEnum convertFromLockType(LockType lockType)
{
LockTypeEnum result = null;
if (lockType != null)
{
switch (lockType)
{
case WRITE_LOCK:
result = LockTypeEnum.write;
break;
case READ_ONLY_LOCK:
result = LockTypeEnum.read;
break;
}
}
return result;
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#createVersion(org.alfresco.repo.webservice.types.Predicate,
* org.alfresco.repo.webservice.types.NamedValue[], boolean)
*/
public VersionResult createVersion(final Predicate items, final NamedValue[] comments, final boolean versionChildren)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<VersionResult>()
{
public VersionResult doWork()
{
// Get the passed nodes
List<NodeRef> nodes = Utils.resolvePredicate(
items,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
// Map the comments into the expected map
Map<String, Serializable> mapComments = new HashMap<String, Serializable>(comments.length);
for (NamedValue value : comments)
{
mapComments.put(value.getName(), value.getValue());
}
List<Reference> versionedReferences = new ArrayList<Reference>(nodes.size());
List<org.alfresco.repo.webservice.types.Version> webServiceVersions = new ArrayList<org.alfresco.repo.webservice.types.Version>(nodes.size());
// Version each node
for (NodeRef node : nodes)
{
Collection<Version> versions = AuthoringWebService.this.versionService.createVersion(node, mapComments, versionChildren);
for (Version version : versions)
{
versionedReferences.add(Utils.convertToReference(version.getVersionedNodeRef()));
webServiceVersions.add(Utils.convertToVersion(version));
}
}
VersionResult result = new VersionResult();
result.setNodes(versionedReferences.toArray(new Reference[versionedReferences.size()]));
result.setVersions(webServiceVersions.toArray(new org.alfresco.repo.webservice.types.Version[webServiceVersions.size()]));
return result;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
e.printStackTrace();
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#getVersionHistory(org.alfresco.repo.webservice.types.Reference)
*/
public VersionHistory getVersionHistory(final Reference node)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<VersionHistory>()
{
public VersionHistory doWork()
{
org.alfresco.service.cmr.version.VersionHistory versionHistory =
AuthoringWebService.this.versionService.getVersionHistory(
Utils.convertToNodeRef(
node,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService));
VersionHistory webServiceVersionHistory = new VersionHistory();
if (versionHistory != null)
{
Collection<Version> versions = versionHistory.getAllVersions();
org.alfresco.repo.webservice.types.Version[] webServiceVersions = new org.alfresco.repo.webservice.types.Version[versions.size()];
int iIndex = 0;
for (Version version : versions)
{
webServiceVersions[iIndex] = Utils.convertToVersion(version);
iIndex ++;
}
webServiceVersionHistory.setVersions(webServiceVersions);
}
return webServiceVersionHistory;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#revertVersion(org.alfresco.repo.webservice.types.Reference,
* java.lang.String)
*/
@SuppressWarnings("unchecked")
public void revertVersion(final Reference node, final String versionLabel)
throws RemoteException, AuthoringFault
{
try
{
TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork()
{
public Object doWork()
{
NodeRef nodeRef = Utils.convertToNodeRef(
node,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
org.alfresco.service.cmr.version.VersionHistory versionHistory = AuthoringWebService.this.versionService.getVersionHistory(nodeRef);
if (versionHistory != null)
{
Version version = versionHistory.getVersion(versionLabel);
if (version != null)
{
AuthoringWebService.this.versionService.revert(nodeRef, version);
}
else
{
throw new RuntimeException("The node could not be reverted because the version label is invalid.");
}
}
else
{
throw new RuntimeException("A unversioned node cannot be reverted.");
}
return null;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#deleteAllVersions(org.alfresco.repo.webservice.types.Reference)
*/
public VersionHistory deleteAllVersions(final Reference node)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<VersionHistory>()
{
public VersionHistory doWork()
{
NodeRef nodeRef = Utils.convertToNodeRef(
node,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
AuthoringWebService.this.versionService.deleteVersionHistory(nodeRef);
return new VersionHistory();
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.axis;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.QueryConfiguration;
import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.description.OperationDesc;
import org.apache.axis.handlers.BasicHandler;
import org.apache.axis.message.SOAPEnvelope;
import org.apache.axis.message.SOAPHeaderElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Axis handler to extract the fetchSize parameter from the QueryConfiguration SOAP header.
* The value of fetchSize is then placed in the MessageContext with a property name of
* ALF_FETCH_SIZE
*
* @author gavinc
*/
public class QueryConfigHandler extends BasicHandler
{
public static final String ALF_FETCH_SIZE = "ALF_FETCH_SIZE";
private static final long serialVersionUID = 6467938074555362971L;
private static Log logger = LogFactory.getLog(QueryConfigHandler.class);
/**
* @see org.apache.axis.Handler#invoke(org.apache.axis.MessageContext)
*/
public void invoke(MessageContext msgContext) throws AxisFault
{
try
{
// determine the method we are calling
String opName = "Unknown method";
OperationDesc op = msgContext.getOperation();
if (op != null)
{
opName = op.getName();
}
// try and find the appropriate header and extract info from it
SOAPEnvelope env = msgContext.getRequestMessage().getSOAPEnvelope();
SOAPHeaderElement header = env.getHeaderByName(Utils.REPOSITORY_SERVICE_NAMESPACE, "QueryHeader");
if (header != null)
{
if (logger.isDebugEnabled())
logger.debug("Found QueryHeader for call to " + opName);
QueryConfiguration queryCfg = (QueryConfiguration)header.getObjectValue(QueryConfiguration.class);
if (queryCfg != null)
{
int fetchSize = queryCfg.getFetchSize();
if (logger.isDebugEnabled())
logger.debug("Fetch size for query = " + fetchSize);
msgContext.setProperty(ALF_FETCH_SIZE, new Integer(fetchSize));
}
else
{
if (logger.isDebugEnabled())
logger.debug("Failed to find QueryConfiguration within QueryHeader");
}
}
else
{
if (logger.isDebugEnabled())
{
logger.debug("QueryHeader was not found for call to " + opName);
}
}
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
logger.debug("Failed to determine fetch size", e);
}
}
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.axis;
import org.alfresco.repo.webservice.Utils;
import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.handlers.soap.SOAPService;
import org.apache.axis.providers.java.RPCProvider;
import org.springframework.web.context.WebApplicationContext;
/**
* A custom Axis RPC Provider that retrieves services via Spring
*
* @author gavinc
*/
public class SpringBeanRPCProvider extends RPCProvider
{
private static final long serialVersionUID = 2173234269124176995L;
private static final String OPTION_NAME = "springBean";
private WebApplicationContext webAppCtx;
/**
* Retrieves the class of the bean represented by the given name
*
* @see org.apache.axis.providers.java.JavaProvider#getServiceClass(java.lang.String, org.apache.axis.handlers.soap.SOAPService, org.apache.axis.MessageContext)
*/
@Override
protected Class getServiceClass(String beanName, SOAPService service, MessageContext msgCtx) throws AxisFault
{
Class clazz = null;
Object bean = getBean(msgCtx, beanName);
if (bean != null)
{
clazz = bean.getClass();
}
return clazz;
}
/**
* @see org.apache.axis.providers.java.JavaProvider#getServiceClassNameOptionName()
*/
@Override
protected String getServiceClassNameOptionName()
{
return OPTION_NAME;
}
/**
* Retrieves the bean with the given name from the current spring context
*
* @see org.apache.axis.providers.java.JavaProvider#makeNewServiceObject(org.apache.axis.MessageContext, java.lang.String)
*/
@Override
protected Object makeNewServiceObject(MessageContext msgCtx, String beanName) throws Exception
{
return getBean(msgCtx, beanName);
}
/**
* Retrieves the bean with the given name from the current spring context
*
* @param msgCtx Axis MessageContext
* @param beanName Name of the bean to lookup
* @return The instance of the bean
*/
private Object getBean(MessageContext msgCtx, String beanName) throws AxisFault
{
return getWebAppContext(msgCtx).getBean(beanName);
}
/**
* Retrieves the Spring context from the web application
*
* @param msgCtx Axis MessageContext
* @return The Spring web app context
*/
private WebApplicationContext getWebAppContext(MessageContext msgCtx) throws AxisFault
{
if (this.webAppCtx == null && msgCtx != null)
{
this.webAppCtx = Utils.getSpringContext(msgCtx);
}
if (this.webAppCtx == null)
{
throw new AxisFault("Failed to retrieve the Spring web application context");
}
return this.webAppCtx;
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.axis;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.webservice.authentication.AuthenticationFault;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.WSPasswordCallback;
/**
* CallbackHandler that verifies the given ticket in the password element of the UsernameToken
* header is still a valid ticket
*
* @author gavinc
*/
public class TicketCallbackHandler implements CallbackHandler
{
private static final Log logger = LogFactory.getLog(TicketCallbackHandler.class);
private AuthenticationService authenticationService;
/**
* Sets the AuthenticationService instance to use
*
* @param authenticationService The AuthenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
/**
* @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
*/
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
{
for (int i = 0; i < callbacks.length; i++)
{
if (callbacks[i] instanceof WSPasswordCallback)
{
WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
String ticket = pc.getPassword();
if (logger.isDebugEnabled())
{
logger.debug("Verifying ticket for: " + pc.getIdentifer());
logger.debug("Ticket: " + ticket);
}
// ensure the ticket is valid
try
{
this.authenticationService.validate(ticket);
}
catch (AuthenticationException ae)
{
if (logger.isDebugEnabled())
logger.debug("Ticket validation failed: " + ae.getMessage());
// NOTE: Throwing AuthenticationFault just gets consumed and the ws-security handler
// reports a missing password; we would need to modify the WSS4J code to let
// the exception bubble up so for now just let the default message get thrown
throw new AuthenticationFault(701, "Authentication failed due to an invalid ticket");
}
if (logger.isDebugEnabled())
logger.debug("Ticket validated successfully");
// if all is well set the password to return as the given ticket
pc.setPassword(pc.getPassword());
}
else
{
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
}
}
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.axis;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.handlers.BasicHandler;
import org.apache.axis.transport.http.HTTPConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* Axis handler that retrieves the TicketCallbackHandler instance from
* a Spring context. The authentication service is injected by Spring
* so that when it gets called by the WSS4J handler it can verify the
* ticket passed to the service.
* The callback handler is then added to the MessageContext under the standard
* WsHandlerConstants.PW_CALLBACK_REF property.
*
* @author gavinc
*/
public class TicketCallbackSpringHandler extends BasicHandler
{
private static final Log logger = LogFactory.getLog(TicketCallbackSpringHandler.class);
private static final String BEAN_NAME = "ticketCallbackHandler";
private static final long serialVersionUID = -135125831180499667L;
/**
* @see org.apache.axis.Handler#invoke(org.apache.axis.MessageContext)
*/
public void invoke(MessageContext msgContext) throws AxisFault
{
// get hold of the Spring context and retrieve the AuthenticationService
HttpServletRequest req = (HttpServletRequest)msgContext.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
ServletContext servletCtx = req.getSession().getServletContext();
WebApplicationContext webAppCtx = WebApplicationContextUtils.getRequiredWebApplicationContext(servletCtx);
TicketCallbackHandler callback = (TicketCallbackHandler)webAppCtx.getBean(BEAN_NAME);
// store the callback in the context where the WS-Security handler can pick it up from
msgContext.setProperty(WSHandlerConstants.PW_CALLBACK_REF, callback);
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.axis;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.Handler;
import org.apache.axis.deployment.wsdd.WSDDProvider;
import org.apache.axis.deployment.wsdd.WSDDService;
/**
* Provider class loaded by Axis, used to identify and
* create an instance of our SpringRPC provider which in
* turn loads service endpoints from Spring configured beans
*
* @see org.alfresco.repo.webservice.axis.SpringBeanRPCProvider
* @author gavinc
*/
public class WSDDSpringBeanRPCProvider extends WSDDProvider
{
private static final String PROVIDER_NAME = "SpringRPC";
/**
* @see org.apache.axis.deployment.wsdd.WSDDProvider#newProviderInstance(org.apache.axis.deployment.wsdd.WSDDService, org.apache.axis.EngineConfiguration)
*/
@Override
public Handler newProviderInstance(WSDDService service, EngineConfiguration registry)
throws Exception
{
return new SpringBeanRPCProvider();
}
/**
* @see org.apache.axis.deployment.wsdd.WSDDProvider#getName()
*/
@Override
public String getName()
{
return PROVIDER_NAME;
}
}

View File

@@ -0,0 +1,454 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.classification;
import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.transaction.TransactionUtil;
import org.alfresco.repo.webservice.AbstractWebService;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.Category;
import org.alfresco.repo.webservice.types.ClassDefinition;
import org.alfresco.repo.webservice.types.Classification;
import org.alfresco.repo.webservice.types.Predicate;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.repo.webservice.types.Store;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.search.CategoryService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Web service implementation of the ClassificationService. The WSDL for this
* service can be accessed from
* http://localhost:8080/alfresco/wsdl/classification-service.wsdl
*
* @author gavinc
*/
public class ClassificationWebService extends AbstractWebService implements
ClassificationServiceSoapPort
{
private static Log logger = LogFactory.getLog(ClassificationWebService.class);
/**
* The category service
*/
private CategoryService categoryService;
/**
* The dictionary service
*/
private DictionaryService dictionaryService;
/**
* The transaction service
*/
private TransactionService transactionService;
/**
* Set the category service
*
* @param categoryService the category service
*/
public void setCategoryService(CategoryService categoryService)
{
this.categoryService = categoryService;
}
/**
* Set the transaction service
*
* @param transactionService the transaction service
*/
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
}
/**
* Set the dictionary service
*
* @param dictionaryService the dictionary service
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* @see org.alfresco.repo.webservice.classification.ClassificationServiceSoapPort#getClassifications()
*/
public Classification[] getClassifications(final Store store) throws RemoteException,
ClassificationFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<Classification[]>()
{
public Classification[] doWork()
{
List<Classification> classifications = new ArrayList<Classification>();
Collection<QName> categoryAspects = ClassificationWebService.this.categoryService.getClassificationAspects();
for (QName aspect : categoryAspects)
{
// Get the title of the cateogry
String title = null;
org.alfresco.service.cmr.dictionary.ClassDefinition aspectDefinition = ClassificationWebService.this.dictionaryService.getClass(aspect);
if (aspectDefinition != null)
{
title = aspectDefinition.getTitle();
}
if (logger.isDebugEnabled())
{
logger.debug("Category aspect found: " + title + " (" + aspect.toString() + ")");
}
Collection<ChildAssociationRef> assocs = ClassificationWebService.this.categoryService.getCategories(
Utils.convertToStoreRef(store),
aspect,
CategoryService.Depth.IMMEDIATE);
for (ChildAssociationRef assoc : assocs)
{
NodeRef categoryNodeRef = assoc.getChildRef();
Classification classification = new Classification();
classification.setClassification(aspect.toString());
classification.setTitle(title);
// TODO set the description
classification.setRootCategory(convertToCategory(categoryNodeRef));
classifications.add(classification);
}
}
return classifications.toArray(new Classification[classifications.size()]);
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new ClassificationFault(0, e.getMessage());
}
}
private Category convertToCategory(NodeRef nodeRef)
{
String title = (String)this.nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
if (logger.isDebugEnabled())
{
logger.debug("Category: " + title + "(" + nodeRef.toString() + ")");
}
Category category = new Category();
category.setId(Utils.convertToReference(nodeRef));
category.setTitle(title);
// TODO need to set the description
return category;
}
/**
* @see org.alfresco.repo.webservice.classification.ClassificationServiceSoapPort#getChildCategories(org.alfresco.repo.webservice.types.Reference)
*/
public Category[] getChildCategories(final Reference parentCategory)
throws RemoteException, ClassificationFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<Category[]>()
{
public Category[] doWork()
{
NodeRef parentNodeRef = Utils.convertToNodeRef(
parentCategory,
ClassificationWebService.this.nodeService,
ClassificationWebService.this.searchService,
ClassificationWebService.this.namespaceService);
Collection<ChildAssociationRef> assocs = ClassificationWebService.this.categoryService.getChildren(
parentNodeRef,
CategoryService.Mode.SUB_CATEGORIES,
CategoryService.Depth.IMMEDIATE);
List<Category> categories = new ArrayList<Category>(assocs.size());
for (ChildAssociationRef assoc : assocs)
{
NodeRef categoryNodeRef = assoc.getChildRef();
categories.add(convertToCategory(categoryNodeRef));
}
return categories.toArray(new Category[categories.size()]);
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new ClassificationFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.classification.ClassificationServiceSoapPort#getCategories(org.alfresco.repo.webservice.types.Predicate)
*/
public CategoriesResult[] getCategories(final Predicate items)
throws RemoteException, ClassificationFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<CategoriesResult[]>()
{
public CategoriesResult[] doWork()
{
List<CategoriesResult> result = new ArrayList<CategoriesResult>();
List<NodeRef> nodeRefs = Utils.resolvePredicate(
items,
ClassificationWebService.this.nodeService,
ClassificationWebService.this.searchService,
ClassificationWebService.this.namespaceService);
for (NodeRef nodeRef : nodeRefs)
{
List<AppliedCategory> appliedCategories = new ArrayList<AppliedCategory>();
Set<QName> apsects = ClassificationWebService.this.nodeService.getAspects(nodeRef);
for (QName aspect : apsects)
{
if (ClassificationWebService.this.dictionaryService.isSubClass(aspect, ContentModel.ASPECT_CLASSIFIABLE) == true)
{
QName categoryPropertyName = getPropertyName(aspect);
if (categoryPropertyName != null)
{
// Get the category value
Collection<NodeRef> categoryNodeRefs = DefaultTypeConverter.INSTANCE.getCollection(
NodeRef.class,
ClassificationWebService.this.nodeService.getProperty(nodeRef, categoryPropertyName));
Reference[] categoryReferences = new Reference[categoryNodeRefs.size()];
int iIndex = 0;
for (NodeRef categoryNodeRef : categoryNodeRefs)
{
categoryReferences[iIndex] = Utils.convertToReference(categoryNodeRef);
iIndex ++;
}
// Create the applied category object
AppliedCategory appliedCategory = new AppliedCategory();
appliedCategory.setClassification(aspect.toString());
appliedCategory.setCategories(categoryReferences);
appliedCategories.add(appliedCategory);
}
}
}
// Create the category result object
CategoriesResult categoryResult = new CategoriesResult();
categoryResult.setNode(Utils.convertToReference(nodeRef));
categoryResult.setCategories(appliedCategories.toArray(new AppliedCategory[appliedCategories.size()]));
result.add(categoryResult);
}
return result.toArray(new CategoriesResult[result.size()]);
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new ClassificationFault(0, e.getMessage());
}
}
/**
* Get the category property qname for a classifiable apsect
*
* @param aspect the aspect qname
* @return the property qname, null if none found
*/
private QName getPropertyName(QName aspect)
{
QName categoryPropertyName = null;
// Need to get category property
org.alfresco.service.cmr.dictionary.ClassDefinition classDefinition = ClassificationWebService.this.dictionaryService.getClass(aspect);
for (PropertyDefinition propertyDefintion : classDefinition.getProperties().values())
{
if (DataTypeDefinition.CATEGORY.equals(propertyDefintion.getDataType().getName()) == true)
{
// We have found the category property (assume there is only one)
categoryPropertyName = propertyDefintion.getName();
break;
}
}
return categoryPropertyName;
}
/**
* @see org.alfresco.repo.webservice.classification.ClassificationServiceSoapPort#setCategories(org.alfresco.repo.webservice.types.Predicate,
* org.alfresco.repo.webservice.classification.AppliedCategory[])
*/
public CategoriesResult[] setCategories(final Predicate items, final AppliedCategory[] categories)
throws RemoteException, ClassificationFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<CategoriesResult[]>()
{
public CategoriesResult[] doWork()
{
List<CategoriesResult> result = new ArrayList<CategoriesResult>();
List<NodeRef> nodeRefs = Utils.resolvePredicate(
items,
ClassificationWebService.this.nodeService,
ClassificationWebService.this.searchService,
ClassificationWebService.this.namespaceService);
for (NodeRef nodeRef : nodeRefs)
{
List<AppliedCategory> appliedCategories = new ArrayList<AppliedCategory>();
for (AppliedCategory category : categories)
{
QName aspect = QName.createQName(category.getClassification());
QName propertyName = getPropertyName(aspect);
if (propertyName != null)
{
// First check that the aspect has been applied to the node
if (ClassificationWebService.this.nodeService.hasAspect(nodeRef, aspect) == false)
{
ClassificationWebService.this.nodeService.addAspect(nodeRef, aspect, null);
}
ArrayList<NodeRef> categoryNodeRefs = new ArrayList<NodeRef>(category.getCategories().length);
for (Reference categoryReference : category.getCategories())
{
categoryNodeRefs.add(Utils.convertToNodeRef(
categoryReference,
ClassificationWebService.this.nodeService,
ClassificationWebService.this.searchService,
ClassificationWebService.this.namespaceService));
}
ClassificationWebService.this.nodeService.setProperty(nodeRef, propertyName, categoryNodeRefs);
// Create the applied category object
AppliedCategory appliedCategory = new AppliedCategory();
appliedCategory.setClassification(category.getClassification());
appliedCategory.setCategories(category.getCategories());
appliedCategories.add(appliedCategory);
}
}
// Create the category result object
CategoriesResult categoryResult = new CategoriesResult();
categoryResult.setNode(Utils.convertToReference(nodeRef));
categoryResult.setCategories(appliedCategories.toArray(new AppliedCategory[appliedCategories.size()]));
result.add(categoryResult);
}
return result.toArray(new CategoriesResult[result.size()]);
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new ClassificationFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.classification.ClassificationServiceSoapPort#describeClassification(org.alfresco.repo.webservice.types.Reference)
*/
public ClassDefinition describeClassification(final String classification)
throws RemoteException, ClassificationFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<ClassDefinition>()
{
public ClassDefinition doWork()
{
org.alfresco.service.cmr.dictionary.ClassDefinition classDefinition = ClassificationWebService.this.dictionaryService.getClass(QName.createQName(classification));
return Utils.setupClassDefObject(classDefinition);
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new ClassificationFault(0, e.getMessage());
}
}
}

View File

@@ -0,0 +1,9 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<import resource="classpath:alfresco/application-context.xml" />
<import resource="classpath:web-services-application-context.xml" />
</beans>

View File

@@ -0,0 +1,300 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.content;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.rmi.RemoteException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.transaction.UserTransaction;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.webservice.AbstractWebService;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.ContentFormat;
import org.alfresco.repo.webservice.types.Predicate;
import org.alfresco.repo.webservice.types.Reference;
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.apache.axis.MessageContext;
import org.apache.axis.transport.http.HTTPConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Web service implementation of the ContentService. The WSDL for this service
* can be accessed from http://localhost:8080/alfresco/wsdl/content-service.wsdl
*
* @author gavinc
*/
public class ContentWebService extends AbstractWebService implements
ContentServiceSoapPort
{
private static Log logger = LogFactory.getLog(ContentWebService.class);
private static final String BROWSER_URL = "{0}://{1}{2}/download/direct/{3}/{4}/{5}/{6}";
/**
* @see org.alfresco.repo.webservice.content.ContentServiceSoapPort#read(org.alfresco.repo.webservice.types.Reference)
*/
public Content[] read(Predicate items, String property)
throws RemoteException, ContentFault
{
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
// resolve the predicates
List<NodeRef> nodes = Utils.resolvePredicate(items, this.nodeService, this.searchService, this.namespaceService);
List<Content> results = new ArrayList<Content>(nodes.size());
for (NodeRef nodeRef : nodes)
{
// Add content to the result
results.add(createContent(nodeRef, property));
}
// commit the transaction
tx.commit();
return results.toArray(new Content[results.size()]);
}
catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
}
catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new ContentFault(0, e.getMessage());
}
}
/**
* Create the content object
*
* @param nodeRef the node reference
* @param property the content property
* @return the content object
* @throws UnsupportedEncodingException
*/
private Content createContent(NodeRef nodeRef, String property)
throws UnsupportedEncodingException
{
Content content = null;
// Lets have a look and see if this node has any content on this node
ContentReader contentReader = this.contentService.getReader(nodeRef, QName.createQName(property));
if (contentReader != null)
{
// Work out what the server, port and context path are
HttpServletRequest req = (HttpServletRequest)MessageContext.getCurrentContext().getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
String address = req.getLocalName();
if (req.getLocalPort() != 80)
{
address = address + ":" + req.getLocalPort();
}
// Get the file name
String filename = (String)this.nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
// format the URL that can be used to download the content
String downloadUrl = MessageFormat.format(BROWSER_URL,
new Object[] { req.getScheme(), address,
req.getContextPath(),
nodeRef.getStoreRef().getProtocol(),
nodeRef.getStoreRef().getIdentifier(),
nodeRef.getId(),
URLEncoder.encode(filename, "UTF-8") });
// Create the content object
ContentFormat format = new ContentFormat(contentReader.getMimetype(), contentReader.getEncoding());
content = new Content(Utils.convertToReference(nodeRef), property, contentReader.getSize(), format, downloadUrl);
// Debug
if (logger.isDebugEnabled())
{
logger.debug("Content: " + nodeRef.getId() + " name="
+ filename + " encoding="
+ content.getFormat().getEncoding() + " mimetype="
+ content.getFormat().getMimetype() + " size="
+ content.getLength() + " downloadURL="
+ content.getUrl());
}
}
else
{
// Create an empty content object
content = new Content(Utils.convertToReference(nodeRef), property, 0, null, null);
// Debug
if (logger.isDebugEnabled())
{
logger.debug("No content found: " + nodeRef.getId());
}
}
return content;
}
/**
* @see org.alfresco.repo.webservice.content.ContentServiceSoapPort#write(org.alfresco.repo.webservice.types.Reference,
* byte[])
*/
public Content write(Reference node, String property, byte[] content, ContentFormat format)
throws RemoteException, ContentFault
{
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
// create a NodeRef from the parent reference
NodeRef nodeRef = Utils.convertToNodeRef(node, this.nodeService,
this.searchService, this.namespaceService);
// Get the content writer
ContentWriter writer = this.contentService.getWriter(nodeRef, QName.createQName(property), true);
// Set the content format details (if they have been specified)
if (format != null)
{
writer.setEncoding(format.getEncoding());
writer.setMimetype(format.getMimetype());
}
// Write the content
writer.putContent(new String(content));
// Debug
if (logger.isDebugEnabled())
{
logger.debug("Updated content for node with id: " + nodeRef.getId());
}
// Commit the transaction
tx.commit();
// Return the content object
return createContent(nodeRef, property);
}
catch (Throwable e)
{
// Rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new ContentFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.content.ContentServiceSoapPort#clear(org.alfresco.repo.webservice.types.Predicate,
* java.lang.String)
*/
public Content[] clear(Predicate items, String property)
throws RemoteException, ContentFault
{
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
List<NodeRef> nodes = Utils.resolvePredicate(items, this.nodeService,this.searchService, this.namespaceService);
Content[] contents = new Content[nodes.size()];
// delete each node in the predicate
for (int x = 0; x < nodes.size(); x++)
{
NodeRef nodeRef = nodes.get(x);
// Clear the content
this.nodeService.setProperty(nodeRef, QName.createQName(property), null);
if (logger.isDebugEnabled())
{
logger.debug("Cleared content node with id: " + nodeRef.getId());
}
contents[x] = createContent(nodeRef, property);
}
// commit the transaction
tx.commit();
return contents;
}
catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new ContentFault(0, e.getMessage());
}
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.repository;
import org.alfresco.util.GUID;
/**
* Abstract implementation of a QuerySession providing support
* for automatic id generation and provides support for
* paging through query results.
*
* @author gavinc
*/
public abstract class AbstractQuerySession implements QuerySession
{
protected int batchSize;
protected int position = 0;
private String id;
/**
* Common constructor that initialises the session's id and batch size
*
* @param batchSize The batch size this session will use
*/
public AbstractQuerySession(int batchSize)
{
this.id = GUID.generate();
this.batchSize = batchSize;
}
/**
* @see org.alfresco.repo.webservice.repository.QuerySession#getId()
*/
public String getId()
{
return this.id;
}
/**
* Calculates the index of the last row to retrieve.
*
* @param totalRowCount The total number of rows in the results
* @return The index of the last row to return
*/
protected int calculateLastRowIndex(int totalRowCount)
{
int lastRowIndex = totalRowCount;
// set the last row index if there are more results available
// than the batch size
if ((this.batchSize != -1) && ((this.position + this.batchSize) < totalRowCount))
{
lastRowIndex = this.position + this.batchSize;
}
return lastRowIndex;
}
/**
* Calculates the value of the next position.
* If the end of the result set is reached the position is set to -1
*
* @param totalRowCount The total number of rows in the results
* @param queryResult The QueryResult object being returned to the client,
* if there are no more results the id is removed from the QueryResult instance
*/
protected void updatePosition(int totalRowCount, QueryResult queryResult)
{
this.position += this.batchSize;
if (this.position >= totalRowCount)
{
// signify that there are no more results
this.position = -1;
queryResult.setQuerySession(null);
}
}
}

View File

@@ -0,0 +1,166 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.repository;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.repo.webservice.types.ResultSetRow;
import org.alfresco.repo.webservice.types.ResultSetRowNode;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Implementation of a QuerySession that stores the results from a query for
* associations
*
* @author Roy Wetherall
*/
public class AssociatedQuerySession extends AbstractQuerySession
{
private static final long serialVersionUID = 6488008047324436124L;
private transient static Log logger = LogFactory
.getLog(AssociatedQuerySession.class);
private Reference node;
/**
* Constructs a AssociatedQuerySession
*
* @param batchSize
* The batch size to use for this session
* @param node
* The node to retrieve the associations
*/
public AssociatedQuerySession(int batchSize, Reference node)
{
super(batchSize);
this.node = node;
}
/**
* @see org.alfresco.repo.webservice.repository.QuerySession#getNextResultsBatch(org.alfresco.service.cmr.search.SearchService,
* org.alfresco.service.cmr.repository.NodeService,
* org.alfresco.service.namespace.NamespaceService)
*/
public QueryResult getNextResultsBatch(SearchService searchService,
NodeService nodeService, NamespaceService namespaceService)
{
QueryResult queryResult = null;
if (this.position != -1)
{
if (logger.isDebugEnabled())
logger.debug("Before getNextResultsBatch: " + toString());
// create the node ref and get the children from the repository
NodeRef nodeRef = Utils.convertToNodeRef(this.node, nodeService,
searchService, namespaceService);
List<AssociationRef> assocs = nodeService.getTargetAssocs(nodeRef,
RegexQNamePattern.MATCH_ALL);
int totalRows = assocs.size();
int lastRow = calculateLastRowIndex(totalRows);
int currentBatchSize = lastRow - this.position;
if (logger.isDebugEnabled())
logger.debug("Total rows = " + totalRows
+ ", current batch size = " + currentBatchSize);
org.alfresco.repo.webservice.types.ResultSet batchResults = new org.alfresco.repo.webservice.types.ResultSet();
org.alfresco.repo.webservice.types.ResultSetRow[] rows = new org.alfresco.repo.webservice.types.ResultSetRow[currentBatchSize];
int arrPos = 0;
for (int x = this.position; x < lastRow; x++)
{
AssociationRef assoc = assocs.get(x);
NodeRef childNodeRef = assoc.getTargetRef();
ResultSetRowNode rowNode = new ResultSetRowNode(childNodeRef
.getId(), nodeService.getType(childNodeRef).toString(),
null);
// create columns for all the properties of the node
// get the data for the row and build up the columns structure
Map<QName, Serializable> props = nodeService
.getProperties(childNodeRef);
NamedValue[] columns = new NamedValue[props.size()];
int col = 0;
for (QName propName : props.keySet())
{
String value = null;
Serializable valueObj = props.get(propName);
if (valueObj != null)
{
value = valueObj.toString();
}
columns[col] = new NamedValue(propName.toString(), value);
col++;
}
ResultSetRow row = new ResultSetRow();
row.setRowIndex(x);
row.setNode(rowNode);
row.setColumns(columns);
// add the row to the overall results
rows[arrPos] = row;
arrPos++;
}
// add the rows to the result set and set the total row count
batchResults.setRows(rows);
batchResults.setTotalRowCount(totalRows);
queryResult = new QueryResult(getId(), batchResults);
// move the position on
updatePosition(totalRows, queryResult);
if (logger.isDebugEnabled())
logger.debug("After getNextResultsBatch: " + toString());
}
return queryResult;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder(super.toString());
builder.append(" (id=").append(getId());
builder.append(" batchSize=").append(this.batchSize);
builder.append(" position=").append(this.position);
builder.append(" node-id=").append(this.node.getUuid()).append(")");
return builder.toString();
}
}

View File

@@ -0,0 +1,152 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.repository;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.repo.webservice.types.ResultSetRow;
import org.alfresco.repo.webservice.types.ResultSetRowNode;
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.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Implementation of a QuerySession that stores the results from a query for children
*
* @author gavinc
*/
public class ChildrenQuerySession extends AbstractQuerySession
{
private static final long serialVersionUID = -5347036309571057074L;
private transient static Log logger = LogFactory.getLog(ChildrenQuerySession.class);
private Reference node;
/**
* Constructs a ChildrenQuerySession
*
* @param batchSize The batch size to use for this session
* @param node The node to retrieve the parents
*/
public ChildrenQuerySession(int batchSize, Reference node)
{
super(batchSize);
this.node = node;
}
/**
* @see org.alfresco.repo.webservice.repository.QuerySession#getNextResultsBatch(org.alfresco.service.cmr.search.SearchService, org.alfresco.service.cmr.repository.NodeService, org.alfresco.service.namespace.NamespaceService)
*/
public QueryResult getNextResultsBatch(SearchService searchService, NodeService nodeService, NamespaceService namespaceService)
{
QueryResult queryResult = null;
if (this.position != -1)
{
if (logger.isDebugEnabled())
logger.debug("Before getNextResultsBatch: " + toString());
// create the node ref and get the children from the repository
NodeRef nodeRef = Utils.convertToNodeRef(this.node, nodeService, searchService, namespaceService);
List<ChildAssociationRef> kids = nodeService.getChildAssocs(nodeRef);
int totalRows = kids.size();
int lastRow = calculateLastRowIndex(totalRows);
int currentBatchSize = lastRow - this.position;
if (logger.isDebugEnabled())
logger.debug("Total rows = " + totalRows + ", current batch size = " + currentBatchSize);
org.alfresco.repo.webservice.types.ResultSet batchResults = new org.alfresco.repo.webservice.types.ResultSet();
org.alfresco.repo.webservice.types.ResultSetRow[] rows = new org.alfresco.repo.webservice.types.ResultSetRow[currentBatchSize];
int arrPos = 0;
for (int x = this.position; x < lastRow; x++)
{
ChildAssociationRef assoc = kids.get(x);
NodeRef childNodeRef = assoc.getChildRef();
ResultSetRowNode rowNode = new ResultSetRowNode(childNodeRef.getId(), nodeService.getType(childNodeRef).toString(), null);
// create columns for all the properties of the node
// get the data for the row and build up the columns structure
Map<QName, Serializable> props = nodeService.getProperties(childNodeRef);
NamedValue[] columns = new NamedValue[props.size()];
int col = 0;
for (QName propName : props.keySet())
{
String value = null;
Serializable valueObj = props.get(propName);
if (valueObj != null)
{
value = valueObj.toString();
}
columns[col] = new NamedValue(propName.toString(), value);
col++;
}
ResultSetRow row = new ResultSetRow();
row.setRowIndex(x);
row.setNode(rowNode);
row.setColumns(columns);
// add the row to the overall results
rows[arrPos] = row;
arrPos++;
}
// add the rows to the result set and set the total row count
batchResults.setRows(rows);
batchResults.setTotalRowCount(totalRows);
queryResult = new QueryResult(getId(), batchResults);
// move the position on
updatePosition(totalRows, queryResult);
if (logger.isDebugEnabled())
logger.debug("After getNextResultsBatch: " + toString());
}
return queryResult;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder(super.toString());
builder.append(" (id=").append(getId());
builder.append(" batchSize=").append(this.batchSize);
builder.append(" position=").append(this.position);
builder.append(" node-id=").append(this.node.getUuid()).append(")");
return builder.toString();
}
}

View File

@@ -0,0 +1,152 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.repository;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.repo.webservice.types.ResultSetRow;
import org.alfresco.repo.webservice.types.ResultSetRowNode;
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.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Implementation of a QuerySession that stores the results from a query for parents
*
* @author gavinc
*/
public class ParentsQuerySession extends AbstractQuerySession
{
private static final long serialVersionUID = 2539375863409175463L;
private transient static Log logger = LogFactory.getLog(ParentsQuerySession.class);
private Reference node;
/**
* Constructs a ParentsQuerySession
*
* @param batchSize The batch size to use for this session
* @param node The node to retrieve the parents
*/
public ParentsQuerySession(int batchSize, Reference node)
{
super(batchSize);
this.node = node;
}
/**
* @see org.alfresco.repo.webservice.repository.QuerySession#getNextResultsBatch(org.alfresco.service.cmr.search.SearchService, org.alfresco.service.cmr.repository.NodeService, org.alfresco.service.namespace.NamespaceService)
*/
public QueryResult getNextResultsBatch(SearchService searchService, NodeService nodeService, NamespaceService namespaceService)
{
QueryResult queryResult = null;
if (this.position != -1)
{
if (logger.isDebugEnabled())
logger.debug("Before getNextResultsBatch: " + toString());
// create the node ref and get the children from the repository
NodeRef nodeRef = Utils.convertToNodeRef(this.node, nodeService, searchService, namespaceService);
List<ChildAssociationRef> parents = nodeService.getParentAssocs(nodeRef);
int totalRows = parents.size();
int lastRow = calculateLastRowIndex(totalRows);
int currentBatchSize = lastRow - this.position;
if (logger.isDebugEnabled())
logger.debug("Total rows = " + totalRows + ", current batch size = " + currentBatchSize);
org.alfresco.repo.webservice.types.ResultSet batchResults = new org.alfresco.repo.webservice.types.ResultSet();
org.alfresco.repo.webservice.types.ResultSetRow[] rows = new org.alfresco.repo.webservice.types.ResultSetRow[currentBatchSize];
int arrPos = 0;
for (int x = this.position; x < lastRow; x++)
{
ChildAssociationRef assoc = parents.get(x);
NodeRef parentNodeRef = assoc.getParentRef();
ResultSetRowNode rowNode = new ResultSetRowNode(parentNodeRef.getId(), nodeService.getType(parentNodeRef).toString(), null);
// create columns for all the properties of the node
// get the data for the row and build up the columns structure
Map<QName, Serializable> props = nodeService.getProperties(parentNodeRef);
NamedValue[] columns = new NamedValue[props.size()];
int col = 0;
for (QName propName : props.keySet())
{
String value = null;
Serializable valueObj = props.get(propName);
if (valueObj != null)
{
value = valueObj.toString();
}
columns[col] = new NamedValue(propName.toString(), value);
col++;
}
ResultSetRow row = new ResultSetRow();
row.setRowIndex(x);
row.setNode(rowNode);
row.setColumns(columns);
// add the row to the overall results
rows[arrPos] = row;
arrPos++;
}
// add the rows to the result set and set the total row count
batchResults.setRows(rows);
batchResults.setTotalRowCount(totalRows);
queryResult = new QueryResult(getId(), batchResults);
// move the position on
updatePosition(totalRows, queryResult);
if (logger.isDebugEnabled())
logger.debug("After getNextResultsBatch: " + toString());
}
return queryResult;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder(super.toString());
builder.append(" (id=").append(getId());
builder.append(" batchSize=").append(this.batchSize);
builder.append(" position=").append(this.position);
builder.append(" node-id=").append(this.node.getUuid()).append(")");
return builder.toString();
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.repository;
import java.io.Serializable;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
/**
* Interface definition for a QuerySession.
*
* @author gavinc
*/
public interface QuerySession extends Serializable
{
/**
* Retrieves the id this query session can be identified as
*
* @return Id of this query session
*/
public String getId();
/**
* Returns a QueryResult object representing the next batch of results.
* QueryResult will contain a maximum of items as determined by the
* <code>fetchSize</code> element of the QueryConfiguration SOAP header.
*
* When the last batch of results is being returned the querySession of
* QueryResult will be null.
*
* @see org.alfresco.repo.webservice.repository.QuerySession#getId()
* @param searchService The SearchService to use for gathering the results
* @param nodeService The NodeService to use for gathering the results
* @param namespaceService The NamespaceService to use
* @return QueryResult containing the next batch of results or null if there
* are no more results
*/
public QueryResult getNextResultsBatch(SearchService searchService, NodeService nodeService,
NamespaceService namespaceService);
}

View File

@@ -0,0 +1,681 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.repository;
import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.transaction.UserTransaction;
import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.webservice.AbstractWebService;
import org.alfresco.repo.webservice.CMLUtil;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.CML;
import org.alfresco.repo.webservice.types.ClassDefinition;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.Node;
import org.alfresco.repo.webservice.types.NodeDefinition;
import org.alfresco.repo.webservice.types.Predicate;
import org.alfresco.repo.webservice.types.Query;
import org.alfresco.repo.webservice.types.QueryLanguageEnum;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.repo.webservice.types.Store;
import org.alfresco.repo.webservice.types.StoreEnum;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.namespace.QName;
import org.apache.axis.MessageContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Web service implementation of the RepositoryService. The WSDL for this
* service can be accessed from
* http://localhost:8080/alfresco/wsdl/repository-service.wsdl
*
* @author gavinc
*/
public class RepositoryWebService extends AbstractWebService implements
RepositoryServiceSoapPort
{
private static Log logger = LogFactory.getLog(RepositoryWebService.class);
private DictionaryService dictionaryService;
private CMLUtil cmlUtil;
private SimpleCache<String, QuerySession> querySessionCache;
/**
* Sets the instance of the DictionaryService to be used
*
* @param dictionaryService
* The DictionaryService
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* Sets the CML Util
*
* @param cmlUtil CML util object
*/
public void setCmlUtil(CMLUtil cmlUtil)
{
this.cmlUtil = cmlUtil;
}
/**
* Sets the instance of the SimpleCache to be used
*
* @param querySessionCache
* The SimpleCache
*/
public void setQuerySessionCache(
SimpleCache<String, QuerySession> querySessionCache)
{
this.querySessionCache = querySessionCache;
}
/**
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#getStores()
*/
public Store[] getStores() throws RemoteException, RepositoryFault
{
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
List<StoreRef> stores = this.nodeService.getStores();
Store[] returnStores = new Store[stores.size()];
for (int x = 0; x < stores.size(); x++)
{
StoreRef storeRef = stores.get(x);
if (logger.isDebugEnabled() == true)
{
logger.debug("Store protocol :" + storeRef.getProtocol());
}
StoreEnum storeEnum = StoreEnum.fromString(storeRef
.getProtocol());
Store store = new Store(storeEnum, storeRef.getIdentifier());
returnStores[x] = store;
}
// commit the transaction
tx.commit();
return returnStores;
} catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new RepositoryFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#query(org.alfresco.repo.webservice.types.Store,
* org.alfresco.repo.webservice.types.Query, boolean)
*/
public QueryResult query(Store store, Query query, boolean includeMetaData)
throws RemoteException, RepositoryFault
{
QueryLanguageEnum langEnum = query.getLanguage();
if (langEnum.equals(QueryLanguageEnum.cql)
|| langEnum.equals(QueryLanguageEnum.xpath))
{
throw new RepositoryFault(110, "Only '"
+ QueryLanguageEnum.lucene.getValue()
+ "' queries are currently supported!");
}
UserTransaction tx = null;
MessageContext msgContext = MessageContext.getCurrentContext();
try
{
tx = Utils.getUserTransaction(msgContext);
tx.begin();
// setup a query session and get the first batch of results
QuerySession querySession = new ResultSetQuerySession(Utils
.getBatchSize(msgContext), store, query, includeMetaData);
QueryResult queryResult = querySession
.getNextResultsBatch(this.searchService, this.nodeService,
this.namespaceService);
// add the session to the cache if there are more results to come
if (queryResult.getQuerySession() != null)
{
// this.querySessionCache.putQuerySession(querySession);
this.querySessionCache.put(queryResult.getQuerySession(),
querySession);
}
// commit the transaction
tx.commit();
return queryResult;
} catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
e.printStackTrace();
throw new RepositoryFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#queryChildren(org.alfresco.repo.webservice.types.Reference)
*/
public QueryResult queryChildren(Reference node) throws RemoteException,
RepositoryFault
{
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
// setup a query session and get the first batch of results
QuerySession querySession = new ChildrenQuerySession(Utils
.getBatchSize(MessageContext.getCurrentContext()), node);
QueryResult queryResult = querySession
.getNextResultsBatch(this.searchService, this.nodeService,
this.namespaceService);
// add the session to the cache if there are more results to come
if (queryResult.getQuerySession() != null)
{
// this.querySessionCache.putQuerySession(querySession);
this.querySessionCache.put(queryResult.getQuerySession(),
querySession);
}
// commit the transaction
tx.commit();
return queryResult;
} catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new RepositoryFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#queryParents(org.alfresco.repo.webservice.types.Reference)
*/
public QueryResult queryParents(Reference node) throws RemoteException,
RepositoryFault
{
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
// setup a query session and get the first batch of results
QuerySession querySession = new ParentsQuerySession(Utils
.getBatchSize(MessageContext.getCurrentContext()), node);
QueryResult queryResult = querySession
.getNextResultsBatch(this.searchService, this.nodeService,
this.namespaceService);
// add the session to the cache if there are more results to come
if (queryResult.getQuerySession() != null)
{
// this.querySessionCache.putQuerySession(querySession);
this.querySessionCache.put(queryResult.getQuerySession(),
querySession);
}
// commit the transaction
tx.commit();
return queryResult;
} catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new RepositoryFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#queryAssociated(org.alfresco.repo.webservice.types.Reference,
* org.alfresco.repo.webservice.repository.Association[])
*/
public QueryResult queryAssociated(Reference node, Association[] association)
throws RemoteException, RepositoryFault
{
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
// setup a query session and get the first batch of results
QuerySession querySession = new AssociatedQuerySession(Utils.getBatchSize(MessageContext.getCurrentContext()), node);
QueryResult queryResult = querySession
.getNextResultsBatch(this.searchService, this.nodeService,
this.namespaceService);
// add the session to the cache if there are more results to come
if (queryResult.getQuerySession() != null)
{
// this.querySessionCache.putQuerySession(querySession);
this.querySessionCache.put(queryResult.getQuerySession(),
querySession);
}
// commit the transaction
tx.commit();
return queryResult;
}
catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new RepositoryFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#fetchMore(java.lang.String)
*/
public QueryResult fetchMore(String querySession) throws RemoteException,
RepositoryFault
{
QueryResult queryResult = null;
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
// try and get the QuerySession with the given id from the cache
QuerySession session = this.querySessionCache.get(querySession);
if (session == null)
{
if (logger.isDebugEnabled())
logger.debug("Invalid querySession id requested: "
+ querySession);
throw new RepositoryFault(4, "querySession with id '"
+ querySession + "' is invalid");
}
// get the next batch of results
queryResult = session.getNextResultsBatch(this.searchService,
this.nodeService, this.namespaceService);
// remove the QuerySession from the cache if there are no more
// results to come
if (queryResult.getQuerySession() == null)
{
this.querySessionCache.remove(querySession);
}
// commit the transaction
tx.commit();
return queryResult;
} catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (e instanceof RepositoryFault)
{
throw (RepositoryFault) e;
} else
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new RepositoryFault(0, e.getMessage());
}
}
}
/**
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#update(org.alfresco.repo.webservice.types.CML)
*/
public UpdateResult[] update(CML statements) throws RemoteException,
RepositoryFault
{
UpdateResult[] result = null;
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
result = this.cmlUtil.executeCML(statements);
// commit the transaction
tx.commit();
return result;
}
catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new RepositoryFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#describe(org.alfresco.repo.webservice.types.Predicate)
*/
public NodeDefinition[] describe(Predicate items) throws RemoteException,
RepositoryFault
{
NodeDefinition[] nodeDefs = null;
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
List<NodeRef> nodes = Utils
.resolvePredicate(items, this.nodeService,
this.searchService, this.namespaceService);
nodeDefs = new NodeDefinition[nodes.size()];
for (int x = 0; x < nodes.size(); x++)
{
nodeDefs[x] = setupNodeDefObject(nodes.get(x));
}
// commit the transaction
tx.commit();
return nodeDefs;
} catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new RepositoryFault(0, e.getMessage());
}
}
/**
* Creates a NodeDefinition web service type object for the given
* repository NodeRef instance
*
* @param nodeRef The NodeRef to generate the NodeDefinition for
* @return The NodeDefinition representation of nodeRef
*/
private NodeDefinition setupNodeDefObject(NodeRef nodeRef)
{
if (logger.isDebugEnabled())
logger.debug("Building NodeDefinition for node: " + nodeRef);
TypeDefinition ddTypeDef = this.dictionaryService
.getType(this.nodeService.getType(nodeRef));
// create the web service ClassDefinition type from the data dictionary TypeDefinition
ClassDefinition typeDef = Utils.setupClassDefObject(ddTypeDef);
// create the web service ClassDefinition types to represent the aspects
ClassDefinition[] aspectDefs = null;
List<AspectDefinition> aspects = ddTypeDef.getDefaultAspects();
if (aspects != null)
{
aspectDefs = new ClassDefinition[aspects.size()];
int pos = 0;
for (AspectDefinition ddAspectDef : aspects)
{
aspectDefs[pos] = Utils.setupClassDefObject(ddAspectDef);
pos++;
}
}
return new NodeDefinition(typeDef, aspectDefs);
}
/**
* Gets the nodes associatiated with the predicate provided. Usefull when the store and ids of the required
* nodes are known.
*
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#get(org.alfresco.repo.webservice.types.Predicate)
*/
public Node[] get(Predicate where) throws RemoteException, RepositoryFault
{
Node[] nodes = null;
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
// Resolve the predicate to a list of node references
List<NodeRef> nodeRefs = Utils.resolvePredicate(where, this.nodeService, this.searchService, this.namespaceService);
nodes = new Node[nodeRefs.size()];
int index = 0;
for (NodeRef nodeRef : nodeRefs)
{
// Get the nodes reference
Reference reference = Utils.convertToReference(nodeRef);
// Get the nodes type
String type = this.nodeService.getType(nodeRef).toString();
// Get the nodes aspects
Set<QName> aspectQNames = this.nodeService.getAspects(nodeRef);
String[] aspects = new String[aspectQNames.size()];
int aspectIndex = 0;
for (QName aspectQName : aspectQNames)
{
aspects[aspectIndex] = aspectQName.toString();
aspectIndex++;
}
// Get the nodes properties
Map<QName, Serializable> propertyMap = this.nodeService.getProperties(nodeRef);
NamedValue[] properties = new NamedValue[propertyMap.size()];
int propertyIndex = 0;
for (Map.Entry<QName, Serializable> entry : propertyMap.entrySet())
{
String value = null;
try
{
value = DefaultTypeConverter.INSTANCE.convert(String.class, entry.getValue());
}
catch (Throwable exception)
{
value = entry.getValue().toString();
}
properties[propertyIndex] = new NamedValue(entry.getKey().toString(), value);
propertyIndex++;
}
// Create the node and add to the array
Node node = new Node(reference, type, aspects, properties);
nodes[index] = node;
index++;
}
// commit the transaction
tx.commit();
}
catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
}
catch (Exception ex)
{
// Ignore
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new RepositoryFault(0, e.getMessage());
}
return nodes;
}
}

View File

@@ -0,0 +1,188 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.repository;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.Query;
import org.alfresco.repo.webservice.types.ResultSetRowNode;
import org.alfresco.repo.webservice.types.Store;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.ResultSetRow;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Implementation of a QuerySession that retrieves results from a repository ResultSet
*
* @author gavinc
*/
public class ResultSetQuerySession extends AbstractQuerySession
{
private static final long serialVersionUID = -9154514445963635138L;
private transient static Log logger = LogFactory.getLog(ResultSetQuerySession.class);
private Store store;
private Query query;
private boolean includeMetaData;
/**
* Constructs a ResultSetQuerySession
*
* @param batchSize The batch size to use for this session
* @param store The repository store to query against
* @param query The query to execute
* @param includeMetaData Whether to include metadata in the query results
*/
public ResultSetQuerySession(int batchSize, Store store, Query query, boolean includeMetaData)
{
super(batchSize);
this.store = store;
this.query = query;
this.includeMetaData = includeMetaData;
}
/**
* @see org.alfresco.repo.webservice.repository.QuerySession#getNextResultsBatch(org.alfresco.service.cmr.search.SearchService, org.alfresco.service.cmr.repository.NodeService, org.alfresco.service.namespace.NamespaceService)
*/
public QueryResult getNextResultsBatch(SearchService searchService, NodeService nodeService, NamespaceService namespaceService)
{
QueryResult queryResult = null;
if (this.position != -1)
{
if (logger.isDebugEnabled())
logger.debug("Before getNextResultsBatch: " + toString());
// handle the special search string of * meaning, get everything
String statement = query.getStatement();
if (statement.equals("*"))
{
statement = "ISNODE:*";
}
ResultSet searchResults = null;
try
{
searchResults = searchService.query(Utils.convertToStoreRef(this.store),
this.query.getLanguage().getValue(), statement);
int totalRows = searchResults.length();
int lastRow = calculateLastRowIndex(totalRows);
int currentBatchSize = lastRow - this.position;
if (logger.isDebugEnabled())
logger.debug("Total rows = " + totalRows + ", current batch size = " + currentBatchSize);
org.alfresco.repo.webservice.types.ResultSet batchResults = new org.alfresco.repo.webservice.types.ResultSet();
org.alfresco.repo.webservice.types.ResultSetRow[] rows = new org.alfresco.repo.webservice.types.ResultSetRow[currentBatchSize];
int arrPos = 0;
for (int x = this.position; x < lastRow; x++)
{
ResultSetRow origRow = searchResults.getRow(x);
NodeRef nodeRef = origRow.getNodeRef();
ResultSetRowNode rowNode = new ResultSetRowNode(nodeRef.getId(), nodeService.getType(nodeRef).toString(), null);
// get the data for the row and build up the columns structure
Map<Path, Serializable> values = origRow.getValues();
NamedValue[] columns = new NamedValue[values.size()];
int col = 0;
for (Path path : values.keySet())
{
String value = null;
Serializable valueObj = values.get(path);
if (valueObj != null)
{
value = valueObj.toString();
}
// Get the attribute QName from the result path
String attributeName = path.last().toString();
if (attributeName.startsWith("@") == true)
{
attributeName = attributeName.substring(1);
}
columns[col] = new NamedValue(attributeName, value);
col++;
}
org.alfresco.repo.webservice.types.ResultSetRow row = new org.alfresco.repo.webservice.types.ResultSetRow();
row.setColumns(columns);
row.setScore(origRow.getScore());
row.setRowIndex(x);
row.setNode(rowNode);
// add the row to the overall results
rows[arrPos] = row;
arrPos++;
}
// TODO: build up the meta data data structure if we've been asked to
// add the rows to the result set and set the total row count
batchResults.setRows(rows);
batchResults.setTotalRowCount(totalRows);
queryResult = new QueryResult(getId(), batchResults);
// move the position on
updatePosition(totalRows, queryResult);
if (logger.isDebugEnabled())
logger.debug("After getNextResultsBatch: " + toString());
}
finally
{
if (searchResults != null)
{
searchResults.close();
}
}
}
return queryResult;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder(super.toString());
builder.append(" (id=").append(getId());
builder.append(" batchSize=").append(this.batchSize);
builder.append(" position=").append(this.position);
builder.append(" store=").append(this.store.getScheme().getValue()).append(":").append(this.store.getAddress());
builder.append(" language=").append(this.query.getLanguage().getValue());
builder.append(" statement=").append(this.query.getStatement());
builder.append(")");
return builder.toString();
}
}

View File

@@ -0,0 +1,138 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<!-- Axis handler to validate the ticket sent with the web service request -->
<bean id="ticketCallbackHandler" class="org.alfresco.repo.webservice.axis.TicketCallbackHandler">
<property name="authenticationService">
<ref bean="authenticationService"/>
</property>
</bean>
<!-- Cache to use to store QuerySession instances -->
<bean id="querySessionCache" class="org.alfresco.repo.cache.EhCacheAdapter">
<property name="cache">
<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean" >
<property name="cacheName">
<value>webservice.QuerySessionCache</value>
</property>
</bean>
</property>
</bean>
<!-- CLM Util bean -->
<bean id="CMLUtil" class="org.alfresco.repo.webservice.CMLUtil">
<property name="nodeService">
<ref bean="NodeService"/>
</property>
<property name="searchService">
<ref bean="SearchService"/>
</property>
<property name="namespaceService">
<ref bean="namespaceService"/>
</property>
<property name="copyService">
<ref bean="copyService"/>
</property>
</bean>
<!-- Implementations of each exposed web service -->
<bean id="authenticationWebService" class="org.alfresco.repo.webservice.authentication.AuthenticationWebService">
<property name="authenticationService">
<ref bean="authenticationService"/>
</property>
</bean>
<bean id="repositoryWebService" class="org.alfresco.repo.webservice.repository.RepositoryWebService">
<property name="nodeService">
<ref bean="NodeService"/>
</property>
<property name="contentService">
<ref bean="ContentService"/>
</property>
<property name="searchService">
<ref bean="SearchService"/>
</property>
<property name="namespaceService">
<ref bean="namespaceService"/>
</property>
<property name="dictionaryService">
<ref bean="dictionaryService"/>
</property>
<property name="querySessionCache">
<ref bean="querySessionCache"/>
</property>
<property name="cmlUtil">
<ref bean="CMLUtil"/>
</property>
</bean>
<bean id="contentWebService" class="org.alfresco.repo.webservice.content.ContentWebService">
<property name="nodeService">
<ref bean="NodeService"/>
</property>
<property name="contentService">
<ref bean="ContentService"/>
</property>
<property name="searchService">
<ref bean="SearchService"/>
</property>
<property name="namespaceService">
<ref bean="namespaceService"/>
</property>
</bean>
<bean id="authoringWebService" class="org.alfresco.repo.webservice.authoring.AuthoringWebService">
<property name="nodeService">
<ref bean="NodeService"/>
</property>
<property name="contentService">
<ref bean="ContentService"/>
</property>
<property name="searchService">
<ref bean="SearchService"/>
</property>
<property name="namespaceService">
<ref bean="namespaceService"/>
</property>
<property name="checkOutCheckinService">
<ref bean="checkOutCheckInService"/>
</property>
<property name="lockService">
<ref bean="lockService"/>
</property>
<property name="versionService">
<ref bean="versionService"/>
</property>
<property name="transactionService">
<ref bean="transactionComponent"/>
</property>
</bean>
<bean id="classificationWebService" class="org.alfresco.repo.webservice.classification.ClassificationWebService">
<property name="nodeService">
<ref bean="NodeService"/>
</property>
<property name="contentService">
<ref bean="ContentService"/>
</property>
<property name="searchService">
<ref bean="SearchService"/>
</property>
<property name="namespaceService">
<ref bean="namespaceService"/>
</property>
<property name="dictionaryService">
<ref bean="dictionaryService"/>
</property>
<property name="categoryService">
<ref bean="CategoryService"/>
</property>
<property name="transactionService">
<ref bean="transactionComponent"/>
</property>
</bean>
</beans>