/*******************************************************************************
* Copyright (c) 2012 IBM Corporation.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
*
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
*
* Keith Wells - initial API and implementation
* Sam Padgett - initial API and Implementation
* Jim Conallen - initial API and implementation
*
*******************************************************************************/
package org.eclipse.lyo.samples.sharepoint;
import java.io.BufferedReader;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
//import jbugz.exceptions.BugzillaException;
import com.sun.jersey.api.client.config.ClientConfig;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.lyo.samples.sharepoint.adapter.SharepointInitializer;
import org.eclipse.lyo.samples.sharepoint.adapter.SharepointResource;
import org.eclipse.lyo.samples.sharepoint.adapter.URLStrategy;
import org.eclipse.lyo.samples.sharepoint.core.IConstants;
import org.eclipse.lyo.samples.sharepoint.exceptions.ConnectionException;
import org.eclipse.lyo.samples.sharepoint.store.ShareServerException;
import org.eclipse.lyo.samples.sharepoint.store.ShareValue;
import org.eclipse.lyo.samples.sharepoint.store.UnrecognizedValueTypeException;
import org.eclipse.lyo.samples.sharepoint.store.ShareValue.ShareValueType;
import org.joda.time.LocalDateTime;
import org.odata4j.consumer.ODataClientRequest;
import org.odata4j.consumer.ODataConsumer;
import org.odata4j.core.OClientBehavior;
import org.odata4j.core.OEntity;
import org.odata4j.core.OProperty;
import org.odata4j.core.ORelatedEntityLink;
import org.odata4j.repack.org.apache.commons.codec.binary.Base64;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* The <code>SharepointConnector</code> class handles all access to a given Sharepoint installation.
* Sharepoint uses OData
*
*
*/
public class SharepointConnector {
/**
* Logger for internal errors.
*/
private static final Log logger = LogFactory.getLog("SharepointConnector.class");
private ODataConsumer odatac;
/**
* Use this method to designate a host to connect to. You must call this method
* before executing any other methods of this object.
*
* @param host A string pointing to the domain of the Sharepoint installation
* @throws ConnectionException if a connection cannot be established
*/
public void connectTo(String host) throws ConnectionException {
connectTo(host,null,null);
}
/**
* Use this method to designate a host to connect to. You must call this method
* before executing any other methods of this object.
*
* If httpUser is not null, than the httpUser and the httpPasswd will be
* used to connect to the sharepoint server. This currently only supports basic
* http authtentication ( @see <a href="http://en.wikipedia.org/wiki/Basic_access_authentication">Basic access authentication</a>).
*
* @param host A string pointing to the domain of the Bugzilla installation
* @param httpUser username for an optional Basic access authentication
* @param httpPasswd password for an optional Basic access authentication
* @throws ConnectionException if a connection cannot be established
*/
public void connectTo(final String host, final String httpUser, final String httpPasswd) throws ConnectionException {
URL hostURL;
try {
hostURL = new URL(host);
} catch (MalformedURLException e) {
logger.error("URL parameter for host is improperly formed; cannot connect", e);
throw new ConnectionException("Host URL is malformed; URL supplied was " + host, e);
}
connectTo(hostURL,httpUser,httpPasswd);
}
/**
* Use this method to designate a host to connect to. You must call this method
* before executing any other methods of this object.
*
* If httpUser is not null, than the httpUser and the httpPasswd will be
* used to connect to the sharepoint server. This currently only supports basic
* http authtentication ( @see <a href="http://en.wikipedia.org/wiki/Basic_access_authentication">Basic access authentication</a>).
*
* @param host A URL of form http:// + somedomain + /_vti_bin/listdata.svc
* @param httpUser username for an optional Basic access authentication
* @param httpPasswd password for an optional Basic access authentication
*
*/
public void connectTo(URL host, String httpUser, String httpPasswd) {
odatac = ODataConsumer.create(
SharepointInitializer.getSharepointUri(),
new OClientBehavior() {
@Override
public ODataClientRequest transform(
ODataClientRequest request) {
String userPassword = SharepointInitializer.getUsername() + ":" + SharepointInitializer.getPassword();
String encoded = Base64.encodeBase64String(userPassword
.getBytes());
encoded = encoded.replaceAll("\r\n?", "");
return request.header("Authorization", "Basic "
+ encoded);
}
@Override
public void modify(ClientConfig arg0) {
// TODO Auto-generated method stub
}
});
}
/*
* Get the document library collections from sharepoint
*/
public List<Library> getLibraries() {
List<Library> libraries = new ArrayList<Library>();
HashMap<String, Object> map;
// get the different collections from Sharepoint
for(String entitySet : odatac.getEntitySets()){
try {
// ignore ReportingTemplates collection, it returns documents we are not interested in
if (!entitySet.startsWith("ReportingTemplates")){
//see if there is a document in the collection, if so let's save it for the catalog
for(OEntity oe1 : odatac.getEntities(entitySet).filter("ContentType eq 'Document'").top(1).execute()) {
map = new HashMap<String,Object>();
map.put("uri", SharepointInitializer.getBaseUri() + '/' + "provider?collection=" + entitySet);
map.put("name", entitySet);
libraries.add(new Library(map));
}
}
} catch(java.lang.RuntimeException ex){
}
}
return libraries;
}
/* public Library getLibrary(String collection) {
HashMap<String, Object> map = new HashMap<String,Object>();
map.put("uri", SharepointInitializer.getBaseUri() + '/' + "provider?collection=" + collection);
map.put("name", collection);
return new Library(map);
}*/
/*
* get the documents
*/
public List<Map<String, ShareValue>> getDocuments() throws UnrecognizedValueTypeException {
HashMap<String, ShareValue> map;
List<Map<String, ShareValue>> documents = new ArrayList<Map<String, ShareValue>>();
for(String entitySet : odatac.getEntitySets()){
try {
// ignore ReportingTemplates collection, it returns documents we are not interested in
if (!entitySet.startsWith("ReportingTemplates")){
for(OEntity oe1 : odatac.getEntities(entitySet).filter("ContentType eq 'Document'").execute()) {
map = new HashMap<String,ShareValue>();
ShareValue shareValue = new ShareValue(ShareValueType.URI, URLStrategy.getResourceBaseURL() + '/' + entitySet + '/' + oe1.getProperty("Id").getValue());
map.put("uri", shareValue);
shareValue = new ShareValue(ShareValueType.STRING, oe1.getProperty("Name").getValue());
map.put("title", shareValue);
documents.add(map);
}
}
} catch(java.lang.RuntimeException ex){
}
}
return documents;
}
/*
* retrieve the documents for a document library collection
*/
public List<Map<String, ShareValue>> getDocuments(String collection) throws UnrecognizedValueTypeException {
HashMap<String, ShareValue> map;
List<Map<String, ShareValue>> documents = new ArrayList<Map<String, ShareValue>>();
try {
//System.out.println(collection);
for(OEntity oe1 : odatac.getEntities(collection).filter("ContentType eq 'Document'").execute()) {
map = new HashMap<String,ShareValue>();
ShareValue shareValue = new ShareValue(ShareValueType.URI, URLStrategy.getResourceBaseURL() + '/' + collection + '/' + oe1.getProperty("Id").getValue());
map.put("uri", shareValue);
shareValue = new ShareValue(ShareValueType.STRING, oe1.getProperty("Name").getValue());
map.put("title", shareValue);
documents.add(map);
}
} catch(java.lang.RuntimeException ex){
System.out.println("exception from odata");
}
return documents;
}
protected String getLinkedEntity(OEntity entity, String link, String property) {
ORelatedEntityLink createdByLink = entity.getLink(link, ORelatedEntityLink.class);
OEntity ocb = odatac.getEntity(createdByLink).execute();
return ocb.getProperty(property).getValue().toString();
}
/*
* Retrieve the metadata about a documetn from sharepoint
*/
public SharepointResource getDocumentProperties(String uri) throws UnrecognizedValueTypeException, ShareServerException {
//System.out.println("getDocumentResource: uri='" + uri + "'");
SharepointResource sharepointResource = new SharepointResource(uri);
//String uri = resource.getUri();
try {
//Split uri -- get /Empire for Entity, get /1 for id
//System.out.println("getDocumentProperties: entered; uri='" + uri +"'" );
//System.out.println("getDocumentProperties: entered; " + URLStrategy.getResourceBaseURL().length() );
if (uri.startsWith(URLStrategy.getResourceBaseURL())) {
String temp = uri.substring(URLStrategy.getResourceBaseURL().length()+1);
String[] tokens = temp.split("/");
OEntity oe = (OEntity) odatac.getEntity(tokens[0], Integer.parseInt(tokens[1])).execute();
for (OProperty<?> p : oe.getProperties()) {
if (p.getName().equals("Id")) {
sharepointResource.setIdentifier(p.getValue().toString());
} else if (p.getName().equals("Name")) {
sharepointResource.setTitle((String) p.getValue());
} else if (p.getName().equals("CreatedById")) {
sharepointResource.setCreator(getLinkedEntity( oe, "CreatedBy", "Name"));
} else if (p.getName().equals("Created")) {
// System.out.println("Created: ='" + p.getValue().toString());
sharepointResource.setCreated(((LocalDateTime) p.getValue()).toDateTime().toDate());
} else if (p.getName().equals("Modified")) {
// System.out.println("Modified: ='" + p.getValue().toString());
sharepointResource.setModified(((LocalDateTime) p.getValue()).toDateTime().toDate());
} else if (p.getName().equals("ModifiedById")) {
sharepointResource.setContributor(getLinkedEntity( oe, "ModifiedBy", "Name"));
} else if (p.getName().equals("ApprovalStatus")) {
sharepointResource.setApprovalStatus((String) p.getValue().toString());
}
}
} else {// TODO problems
System.out.println("uri did not start correctly");
}
} catch (Exception e) {
System.err.println(e);
}
return sharepointResource;
}
/*
* Create a document in sharepoint using the UI delegate
*/
public int createDocument(HttpServletResponse response, String library, FileItem item) throws UnrecognizedValueTypeException, ShareServerException {
// System.out.println("createDocument: uri='" + uri + "'");
//SharepointResource sharepointResource = new SharepointResource(uri);
// String filename = resource.getSource();
//
// OEntity newProduct = odatac.createEntity("Empire").properties(OProperties.int32("Id", 10))
// .properties(OProperties.string("Name", filename))
// .properties(OProperties.string("ContentType","Document"))
// .properties(OProperties.string("Title","Architecture"))
// .properties(OProperties.string("ApprovalStatus","2"))
// .properties(OProperties.string("Path","/Empire"))
// .execute();
// no obvious API in odata4j to create a document, default apache http Create
HttpClient client = new HttpClient();
client.getParams().setParameter("http.useragent", "Test Client");
BufferedReader br = null;
int returnCode =500;
PostMethod method = null;
try {
client.setConnectionTimeout(8000);
method = new PostMethod(SharepointInitializer.getSharepointUri() + "/" + library);
String userPassword = SharepointInitializer.getUsername() + ":" + SharepointInitializer.getPassword();
String encoding = Base64.encodeBase64String(userPassword.getBytes());
encoding = encoding.replaceAll("\r\n?", "");
method.setRequestHeader("Authorization", "Basic " + encoding);
method.addRequestHeader("Content-type", item.getContentType());
method.addRequestHeader(IConstants.HDR_SLUG, "/" + library + "/" + item.getName());
//InputStream is = new FileInputStream("E:\\odata\\sharepoint\\DeathStarTest.doc");
RequestEntity entity = new InputStreamRequestEntity(
item.getInputStream(),
"application/msword");
method.setRequestEntity(entity);
method.setDoAuthentication( true );
returnCode = client.executeMethod(method);
if(returnCode == HttpStatus.SC_NOT_IMPLEMENTED) {
System.err.println("The Post method is not implemented by this URI");
// still consume the response body
method.getResponseBodyAsString();
} else {
//br = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream()));
InputStream is = method.getResponseBodyAsStream();
//br = new BufferedReader(new InputStreamReader(is));
// String readLine;
// while(((readLine = br.readLine()) != null)) {
// System.out.println(readLine);
// }
response.setContentType("text/html");
//response.setContentType("application/atom+xml");
//response.setContentLength(is.getBytes().length);
response.setStatus(IConstants.SC_OK);
//response.getWriter().write("<html><head><title>hello world</title></head><body><p>hello world!</p></body></html>");
//response.getWriter().write(method.getResponseBodyAsString());
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder parser = factory.newDocumentBuilder();
Document doc = parser.parse(is);
Element root = doc.getDocumentElement();
System.out.println ("Root element of the doc is " + root.getNodeName());
// String msftdPrefix = "http://schemas.microsoft.com/ado/2007/08/dataservices";
// String msftmPrefix = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";
String id = null;
String name = null;
NodeList nl = root.getElementsByTagName("d:Id");
if (nl.getLength() > 0) {
id = nl.item(0).getFirstChild().getNodeValue();
}
//nl = root.getElementsByTagName("d:ContentType");
//if (nl.getLength() > 0) {
// type = nl.item(0).getFirstChild().getNodeValue();
//}
nl = root.getElementsByTagName("d:Name");
if (nl.getLength() > 0) {
name = nl.item(0).getFirstChild().getNodeValue();
}
response.getWriter().write("<html>");
response.getWriter().write("<head>");
response.getWriter().write("</head>");
response.getWriter().write("<body>");
response.getWriter().write("<p>" + name + " was created with an Id =" + id +"</p>" );
response.getWriter().write("</body>");
response.getWriter().write("</html>");
//response.getWriter().write(is.content);
//String readLine;
//while(((readLine = br.readLine()) != null)) {
// response.getWriter().write(readLine);
//}
//response.setContentType(IConstants.CT_XML);
//response.getWriter().write(is.toString());
//response.setStatus(IConstants.SC_OK);
//test
// String readLine;
// while(((readLine = br.readLine()) != null)) {
// System.out.println(readLine);
// }
}
} catch (Exception e) {
System.err.println(e);
e.printStackTrace();
} finally {
if (method != null) method.releaseConnection();
if(br != null) try { br.close(); } catch (Exception fe) {}
}
return returnCode;
}
}