1) Let`s create new Maven project and add dependencies:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.axis</groupId>
<artifactId>axis</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>axis</groupId>
<artifactId>axis-jaxrpc</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>commons-discovery</groupId>
<artifactId>commons-discovery</artifactId>
<version>0.4</version>
<scope>test</scope>
</dependency>
</dependencies>
2) For copying files we`ll use sharepoint`s web services :Copy and for creating new folders : Lists. This services situated on http://yoursharepointurl/_vti_bin/Copy.asmx and http://yoursharepointurl/_vti_bin/Lists.asmx
I found a maven plugin which generate all java classes from wsdl file.
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>axistools-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
<configuration>
<outputDirectory>${project.build.directory}/${project.artifactId}/generated-sources</outputDirectory>
<timestampDirectory>${project.build.directory}/${project.artifactId}/generated-sources</timestampDirectory>
<testSourceDirectory>${project.build.directory}/${project.artifactId}/generated-test-sources</testSourceDirectory>
<serverSide>false</serverSide>
<subPackageByFileName>false</subPackageByFileName>
<typeMappingVersion>1.1</typeMappingVersion>
<testCases>false</testCases>
<runTestCasesAsUnitTests>false</runTestCasesAsUnitTests>
</configuration>
</plugin>
</plugins>
3) Save your wsdl files to src/main/wsdl folder and run maven goal generate-sources. Plugin will generate all java classes. Add these files to build path to Eclipse.
4) Now time is to create SharepointService.java class. Add constructor
public SharePointService(String serviceUrl, String userPassword, String userName) {5) add private methods to initialise listsService and copyService. In case if you have NTLM authentication you should look here : http://derekjmiller.spaces.live.com/blog/cns!A77124B9D0EE317F!142.entry
this.servicesUrl = serviceUrl;
this.userName = userName;
this.userPassword = userPassword;
this.listsService = initListService();
this.copyService = initCopyService();
}
public CopySoap12Stub initCopyService() {
CopySoap12Stub stub;
CopyLocator locator = new CopyLocator();
try {
URL url = new URL(this.servicesUrl + COPY_SERVICE);
stub = (CopySoap12Stub) locator.getCopySoap12(url);
stub.setUsername(this.userName);
stub.setPassword(this.userPassword);
return stub;
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceException e) {
e.printStackTrace();
}
return null;
}
and for lists service :
private ListsSoap12Stub initListService() {6) I added rootPath property - this is the document library on where folders and file will be uploaded
if (this.listsService != null)
return this.listsService;
ListsSoap12Stub stub;
ListsLocator locator = new ListsLocator();
try {
URL url = new URL(this.servicesUrl + LISTS_SERVICE);
stub = (ListsSoap12Stub) locator.getListsSoap12(url);
stub.setUsername(userName);
stub.setPassword(userPassword);
return stub;
} catch (MalformedURLException e) {
logger.error(e.getMessage());
} catch (ServiceException e) {
logger.error(e.getMessage());
} catch (Exception ex) {
logger.error(ex.getMessage());
}
return null;
}
private String rootPath;
public void setRootPath(String path) {
this.rootPath = path;
}
public String getRootPath() {
if (this.rootPath == null) {
return DEFAULT_ROOT_FOLDER;
} else
return this.rootPath;
}
7) Interface of our upload-method will be : uploadDocument(String path, File file) where path - path where to upload file, relative to the RootPath and file - simple java.io.File.
Bad news is thst copy service CANT create folders, just copy file. Good news - we can to this with Lists service.
Here the implementation:
private void makeNewFolder(String relativePath) throws SOAPException,
RemoteException {
UpdateListItemsUpdates updates;
String[] folderNames = relativePath.split("/");
if (folderNames.length == 0) {
logger
.info("Path should have delimiters: example: ParentFolder/ChildFolder");
return;
} else {
String currentFolder = folderNames[0];
for (int i = 0; i < folderNames.length; i++) {
if (i > 0) {
currentFolder += "/" + folderNames[i];
}
updates = new UpdateListItemsUpdates(BatchCreator
.createNewFolderBatch(currentFolder));
listsService.updateListItems(DEFAULT_ROOT_FOLDER, updates);
}
}
}
The main thing here is - updateListItems method . We need to pass 2 parameters there :
DEFAULT_ROOT_FOLDER - name of the list (name of the shared library, which we will update)
updates - Wrapper of MessageElement[] . We create it in our utill class BatchCreator in createNewFolderBatch method:
8) Ant the last - put it all together implementing uploadDocument(String path, File file) method:
public void uploadDocument(String path, File file)
throws FileAlreadyExistsException, SOAPException {
try {
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(file));
byte[] bytes = new byte[bis.available()];
bis.read(bytes);
FieldInformation fieldInformation = new FieldInformation();
fieldInformation.setDisplayName(file.getName());
fieldInformation.setInternalName(file.getName());
FieldInformationCollection infos = new FieldInformationCollection(
new FieldInformation[] { fieldInformation });
makeNewFolder(path);
String sourceUrl = getServiceUrl() + "/" + getRootPath() + "/"
+ path + "/" + file.getName();
DestinationUrlCollection destinationUrls = new DestinationUrlCollection(
new String[] { sourceUrl });
UnsignedIntHolder copyIntoItemsResult = new UnsignedIntHolder(
new UnsignedInt());
CopyResultCollectionHolder results = new CopyResultCollectionHolder(
new CopyResultCollection(
new CopyResult[] { new CopyResult() }));
copyService.copyIntoItems(sourceUrl, destinationUrls, infos, bytes,
copyIntoItemsResult, results);
// error message always exists
String errorMessage = results.value.getCopyResult()[0]
.getErrorMessage();
if (errorMessage != null) {
throw new FileAlreadyExistsException("File already exists in directory");
} else {
logger.info("file " + file.getName()
+ " has been successfully uploaded to server" + "\n "
+ getServiceUrl() + "/" + getRootPath() + "/" + path
+ "/" + file.getName());
}
} catch (FileNotFoundException e) {
logger.error(e.getMessage());
} catch (IOException e) {
logger.error(e.getMessage());
}
}
This works for me and i hope will be work for you. ;)
This is very impressive. I'm having a few issues with compilation (such as this signature not being found:
ВідповістиВидалитиFieldInformationCollection infos = new FieldInformationCollection( new FieldInformation[] { fieldInformation });
Do you have the ability to post a zip file of this solution?
Thanks a lot.
unfortunately i`ve lost all sources, but as i remember FieldInformationCollection class should be generated by wsdl2java from sharepoint COPY-webservice http://msdn.microsoft.com/en-us/library/dd920449.aspx
ВідповістиВидалитиHi, Thanks for such informative post. I am trying to create a folder in sahrepoint. while trying that I got stuck on this line.
ВідповістиВидалитиupdates = new UpdateListItemsUpdates(BatchCreator
.createNewFolderBatch(currentFolder));
I didnt understand where did you get UpdateListItemsUpdates class from. Your post doesnot tell about this class and neither I could find it in Lists.asmx
Please let how to pass the MessageElement[] in UpdateListItems()
Thanks again