blob: c97c2885d54e89a12117bec36e94f7e111c3d21a [file] [log] [blame]
// Copyright 2012 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// 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 com.google.enterprise.adaptor.sharepoint;
import com.google.enterprise.adaptor.AbstractAdaptor;
import com.google.enterprise.adaptor.AdaptorContext;
import com.google.enterprise.adaptor.Config;
import com.google.enterprise.adaptor.DocId;
import com.google.enterprise.adaptor.DocIdEncoder;
import com.google.enterprise.adaptor.DocIdPusher;
import com.google.enterprise.adaptor.IOHelper;
import com.google.enterprise.adaptor.Request;
import com.google.enterprise.adaptor.Response;
import org.apache.axis2.AxisFault;
import org.apache.axis2.client.Options;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.transport.http.HttpTransportProperties;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.GetMethod;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.concurrent.*;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
/**
* SharePoint Adaptor for the GSA.
*/
public class SharePointAdaptor extends AbstractAdaptor {
private final ConcurrentMap<String, SiteDataClient> clients
= new ConcurrentSkipListMap<String, SiteDataClient>();
private final XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
private final DocId virtualServerDocId = new DocId("");
private AdaptorContext context;
// Configuration-provided values.
private String virtualServer;
private String username;
private String password;
@Override
public void initConfig(Config config) {
config.addKey("sharepoint.server", null);
config.addKey("sharepoint.username", null);
config.addKey("sharepoint.password", null);
}
@Override
public void init(AdaptorContext context) {
this.context = context;
Config config = context.getConfig();
virtualServer = config.getValue("sharepoint.server");
username = config.getValue("sharepoint.username");
password = config.getValue("sharepoint.password");
}
@Override
public void getDocContent(Request request, Response response)
throws IOException {
try {
DocId id = request.getDocId();
SiteDataClient virtualServerClient = getSiteDataClient(virtualServer);
if (id.equals(virtualServerDocId)) {
virtualServerClient.getVirtualServerDocContent(request, response);
} else {
SiteDataClient client
= virtualServerClient.getClientForUrl(id.getUniqueId());
client.getDocContent(request, response);
}
} catch (RuntimeException ex) {
throw ex;
} catch (IOException ex) {
throw ex;
} catch (Exception ex) {
throw new IOException(ex);
}
}
@Override
public void getDocIds(DocIdPusher pusher) throws InterruptedException {
pusher.pushDocIds(Arrays.asList(virtualServerDocId));
}
private SiteDataClient getSiteDataClient(String site) throws AxisFault {
SiteDataClient client = clients.get(site);
if (client == null) {
client = new SiteDataClient(site);
clients.putIfAbsent(site, client);
client = clients.get(site);
}
return client;
}
public static void main(String[] args) throws Exception {
if (false) {
final String logPackage = "org.apache.commons.logging.";
System.setProperty(logPackage + "Log", logPackage + "impl.SimpleLog");
System.setProperty(logPackage + "simplelog.log.httpclient.wire", "debug");
System.setProperty(
logPackage + "simplelog.log.org.apache.commons.httpclient", "debug");
}
AbstractAdaptor.main(new SharePointAdaptor(), args);
}
private class SiteDataClient {
private static final boolean DEBUG = false;
private static final String XMLNS
= "http://schemas.microsoft.com/sharepoint/soap/";
private final SiteDataStub stub;
private final String siteUrl;
public SiteDataClient(String site) throws AxisFault {
if (!site.endsWith("/")) {
// Always end with a '/' for a cannonical form.
site = site + "/";
}
this.siteUrl = site;
this.stub = new SiteDataStub(site + "_vti_bin/SiteData.asmx");
HttpTransportProperties.Authenticator auth
= new HttpTransportProperties.Authenticator();
auth.setUsername(username);
auth.setPassword(password);
auth.setPreemptiveAuthentication(true);
Options options = stub._getServiceClient().getOptions();
options.setProperty(HTTPConstants.AUTHENTICATE, auth);
options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, true);
}
private void getDocContent(Request request, Response response)
throws Exception {
SiteDataStub.GetURLSegments urlRequest
= new SiteDataStub.GetURLSegments();
urlRequest.setStrURL(request.getDocId().getUniqueId());
SiteDataStub.GetURLSegmentsResponse urlResponse
= stub.getURLSegments(urlRequest);
if (!urlResponse.getGetURLSegmentsResult()) {
response.respondNotFound();
return;
}
if (urlResponse.getStrWebID() != null) {
getSiteDocContent(request, response, urlResponse.getStrWebID());
} else if (urlResponse.getStrItemID() != null) {
getListItemDocContent(request, response, urlResponse.getStrListID(),
urlResponse.getStrItemID());
} else if (urlResponse.getStrListID() != null) {
getListDocContent(request, response, urlResponse.getStrListID());
} else if (urlResponse.getStrBucketID() != null) {
response.respondNotFound();
} else {
// Assume it is a top-level site.
getSiteDocContent(request, response, urlResponse.getStrWebID());
}
}
public void callChangesContentDatabase() throws Exception {
System.out.println(" ContentDatabase Changes");
SiteDataStub.GetChanges request = new SiteDataStub.GetChanges();
request.setObjectType(SiteDataStub.ObjectType.ContentDatabase);
request.setContentDatabaseId("{4fb7dea1-2912-4927-9eda-1ea2f0977cf8}");
request.setLastChangeId(
"1;0;4fb7dea1-2912-4927-9eda-1ea2f0977cf8;634704678460030000;261");
//request.setCurrentChangeId("");
request.setTimeout(2);
SiteDataStub.GetChangesResponse response = stub.getChanges(request);
System.out.println(response.getMoreChanges());
System.out.println(response.getCurrentChangeId());
System.out.println(response.getLastChangeId());
System.out.println(response.getGetChangesResult());
}
private String encodeUrl(String url) {
if (url.toLowerCase().startsWith("https://")
|| url.toLowerCase().startsWith("http://")) {
// Leave as-is.
} else if (!url.startsWith("/")) {
url = siteUrl + url;
} else {
// Rip off everthing after the third slash (including the slash).
// Get http://example.com from http://example.com/some/folder.
String[] parts = siteUrl.split("/", 4);
url = parts[0] + "//" + parts[2] + url;
}
URI uri = context.getDocIdEncoder().encodeDocId(new DocId(url));
return uri.toASCIIString();
}
private String liUrl(String url) {
// TODO(ejona): Fix raw string concatenation.
return "<li><a href=\"" + encodeUrl(url) + "\">" + url + "</a></li>";
}
private void getVirtualServerDocContent(Request request, Response response)
throws Exception {
SiteDataStub.VirtualServer vs = getContentVirtualServer();
response.setContentType("text/html");
Writer writer = new OutputStreamWriter(response.getOutputStream());
writer.write("<!DOCTYPE html>\n"
+ "<html><head>"
+ "<title>VirtualServer " + vs.getMetadata().getURL() + "</title>"
+ "</head>"
+ "<body>"
+ "<h1>VirtualServer " + vs.getMetadata().getURL() + "</h1>"
+ "<p>Sites</p>"
+ "<ul>");
if (vs.getContentDatabases() != null) {
DocIdEncoder encoder = context.getDocIdEncoder();
for (SiteDataStub.ContentDatabase_type0 cd_t0
: vs.getContentDatabases().getContentDatabase()) {
SiteDataStub.ContentDatabase cd
= getContentContentDatabase(cd_t0.getID());
if (cd.getSites() != null && cd.getSites().getSite() != null) {
for (SiteDataStub.Site_type0 site : cd.getSites().getSite()) {
writer.write(liUrl(site.getURL()));
}
}
}
}
writer.write("</ul></body></html>");
writer.flush();
}
private void getSiteDocContent(Request request, Response response,
String id) throws Exception {
SiteDataStub.Web w = getContentWeb(id);
response.setContentType("text/html");
Writer writer = new OutputStreamWriter(response.getOutputStream());
writer.write("<!DOCTYPE html>\n"
+ "<html><head>"
+ "<title>Site " + w.getMetadata().getTitle() + "</title>"
+ "</head>"
+ "<body>"
+ "<h1>Site " + w.getMetadata().getTitle() + "</h1>");
// TODO: w.getMetadata().getNoIndex()
DocIdEncoder encoder = context.getDocIdEncoder();
if (w.getWebs() != null && w.getWebs().getWeb() != null) {
writer.write("<p>Sites</p><ul>");
for (SiteDataStub.Web_type0 web : w.getWebs().getWeb()) {
writer.write(liUrl(web.getURL()));
}
writer.write("</ul>");
}
if (w.getLists() != null && w.getLists().getList() != null) {
writer.write("<p>Lists</p><ul>");
for (SiteDataStub.List_type0 list : w.getLists().getList()) {
writer.write(liUrl(list.getDefaultViewUrl()));
}
writer.write("</ul>");
}
if (w.getFPFolder() != null) {
getFolderDataDocContent(writer, w.getFPFolder());
}
writer.write("</body></html>");
writer.flush();
}
private void getListDocContent(Request request, Response response,
String id) throws Exception {
SiteDataStub.List l = getContentList(id);
response.setContentType("text/html");
Writer writer = new OutputStreamWriter(response.getOutputStream());
writer.write("<!DOCTYPE html>\n"
+ "<html><head>"
+ "<title>List " + l.getMetadata().getTitle() + "</title>"
+ "</head>"
+ "<body>"
+ "<h1>List " + l.getMetadata().getTitle() + "</h1>");
if ("DocumentLibrary".equals(l.getMetadata().getBaseType().getValue())) {
SiteDataStub.FPFolder f
= getContentFolder(l.getMetadata().getRootFolder());
getFolderDataDocContent(writer, f.getFPFolder());
} else {
writer.write("<p>List Items</p><ul>");
for (int i = 0; i < l.getMetadata().getItemCount(); i++) {
// TODO: determine URLs to provide.
}
writer.write("</ul>");
}
writer.write("</body></html>");
writer.flush();
}
private void getFolderDataDocContent(Writer writer,
SiteDataStub.FolderData f) throws IOException {
if (f.getFolders() != null) {
writer.write("<p>Folders</p><ul>");
for (SiteDataStub.Folders folders : f.getFolders()) {
if (folders.getFolder() != null) {
for (SiteDataStub.Folder_type0 folder : folders.getFolder()) {
writer.write(liUrl(folder.getURL()));
}
}
}
writer.write("</ul>");
}
if (f.getFiles() != null) {
writer.write("<p>Files</p><ul>");
for (SiteDataStub.Files files : f.getFiles()) {
if (files.getFile() != null) {
for (SiteDataStub.File_type0 file : files.getFile()) {
writer.write(liUrl(file.getURL()));
}
}
}
writer.write("</ul>");
}
}
private void recurseFile(String id, String url, String prefix)
throws Exception {
System.out.println(prefix + "File: " + url);
prefix += " ";
System.out.println(prefix + "ID=" + id);
}
private void getListItemDocContent(Request request, Response response,
String listId, String itemId) throws Exception {
//SiteDataStub.ItemData i = getContentItem(listId, itemId);
HttpClient client = new HttpClient();
client.getParams().setAuthenticationPreemptive(true);
Credentials creds
= new UsernamePasswordCredentials(username, password);
client.getState().setCredentials(AuthScope.ANY, creds);
String url = request.getDocId().getUniqueId();
String[] parts = url.split("/", 4);
url = parts[0] + "/" + parts[1] + "/" + parts[2] + "/" +
new URI(null, null, parts[3], null).toASCIIString();
GetMethod method = new GetMethod(url);
int statusCode = client.executeMethod(method);
if (statusCode != HttpStatus.SC_OK) {
throw new RuntimeException("Got status code: " + statusCode);
}
InputStream is = method.getResponseBodyAsStream();
IOHelper.copyStream(is, response.getOutputStream());
}
private SiteDataStub.VirtualServer getContentVirtualServer()
throws Exception {
SiteDataStub.GetContent request = new SiteDataStub.GetContent();
request.setObjectType(SiteDataStub.ObjectType.VirtualServer);
request.setRetrieveChildItems(true);
request.setSecurityOnly(false);
SiteDataStub.GetContentResponse response = stub.getContent(request);
if (DEBUG) {
System.out.println(" VirtualServer");
System.out.println(response.getLastItemIdOnPage());
System.out.println(response.getGetContentResult());
}
String xml = response.getGetContentResult();
xml = xml.replace("<VirtualServer>",
"<VirtualServer xmlns='" + XMLNS + "'>");
XMLStreamReader reader = xmlInputFactory.createXMLStreamReader(
new StringReader(xml));
return SiteDataStub.VirtualServer.Factory.parse(reader);
}
private SiteDataClient getClientForUrl(String url) throws Exception {
SiteDataStub.GetSiteUrl request = new SiteDataStub.GetSiteUrl();
request.setUrl(url);
SiteDataStub.GetSiteUrlResponse response = stub.getSiteUrl(request);
return getSiteDataClient(response.getSiteUrl());
}
private SiteDataStub.ContentDatabase getContentContentDatabase(String id)
throws Exception {
SiteDataStub.GetContent request = new SiteDataStub.GetContent();
request.setObjectType(SiteDataStub.ObjectType.ContentDatabase);
request.setRetrieveChildItems(true);
request.setSecurityOnly(false);
request.setObjectId(id);
SiteDataStub.GetContentResponse response = stub.getContent(request);
if (DEBUG) {
System.out.println(" ContentDatabase");
System.out.println(response.getLastItemIdOnPage());
System.out.println(response.getGetContentResult());
}
String xml = response.getGetContentResult();
xml = xml.replace("<ContentDatabase>",
"<ContentDatabase xmlns='" + XMLNS + "'>");
XMLStreamReader reader = xmlInputFactory.createXMLStreamReader(
new StringReader(xml));
return SiteDataStub.ContentDatabase.Factory.parse(reader);
}
private SiteDataStub.Web getContentWeb(String id) throws Exception {
SiteDataStub.GetContent request = new SiteDataStub.GetContent();
request.setObjectType(SiteDataStub.ObjectType.Site);
request.setRetrieveChildItems(true);
request.setSecurityOnly(false);
request.setObjectId(id);
SiteDataStub.GetContentResponse response = stub.getContent(request);
if (DEBUG) {
System.out.println(" Web");
System.out.println(id);
System.out.println(response.getLastItemIdOnPage());
System.out.println(response.getGetContentResult());
}
stub.getContent(request);
String xml = response.getGetContentResult();
xml = xml.replace("<Web>", "<Web xmlns='" + XMLNS + "'>");
XMLStreamReader reader = xmlInputFactory.createXMLStreamReader(
new StringReader(xml));
return SiteDataStub.Web.Factory.parse(reader);
}
private SiteDataStub.List getContentList(String id) throws Exception {
SiteDataStub.GetContent request = new SiteDataStub.GetContent();
request.setObjectType(SiteDataStub.ObjectType.List);
request.setRetrieveChildItems(true);
request.setSecurityOnly(false);
request.setObjectId(id);
SiteDataStub.GetContentResponse response = stub.getContent(request);
if (DEBUG) {
System.out.println(" List");
System.out.println(response.getLastItemIdOnPage());
System.out.println(response.getGetContentResult());
}
String xml = response.getGetContentResult();
xml = xml.replace("<List>", "<List xmlns='" + XMLNS + "'>");
XMLStreamReader reader = xmlInputFactory.createXMLStreamReader(
new StringReader(xml));
return SiteDataStub.List.Factory.parse(reader);
}
private SiteDataStub.ItemData getContentItem(String listId, String itemId)
throws Exception {
SiteDataStub.GetContent request = new SiteDataStub.GetContent();
request.setObjectType(SiteDataStub.ObjectType.ListItem);
request.setRetrieveChildItems(true);
request.setSecurityOnly(false);
request.setObjectId(listId);
request.setFolderUrl("");
request.setItemId(itemId);
SiteDataStub.GetContentResponse response = stub.getContent(request);
if (DEBUG) {
System.out.println(" ListItem");
System.out.println(response.getLastItemIdOnPage());
System.out.println(response.getGetContentResult());
}
String xml = response.getGetContentResult();
xml = xml.replace("<Item>", "<ItemData xmlns='" + XMLNS + "'>");
xml = xml.replace("</Item>", "</ItemData>");
XMLStreamReader reader = xmlInputFactory.createXMLStreamReader(
new StringReader(xml));
return SiteDataStub.ItemData.Factory.parse(reader);
}
private SiteDataStub.FPFolder getContentFolder(String url)
throws Exception {
SiteDataStub.GetContent request = new SiteDataStub.GetContent();
request.setObjectType(SiteDataStub.ObjectType.Folder);
request.setRetrieveChildItems(true);
request.setSecurityOnly(false);
request.setFolderUrl(url);
SiteDataStub.GetContentResponse response = stub.getContent(request);
if (DEBUG) {
System.out.println(" Folder (Specific)");
System.out.println(response.getLastItemIdOnPage());
System.out.println(response.getGetContentResult());
}
String xml = response.getGetContentResult();
xml = xml.replace("<FPFolder>", "<FPFolder xmlns='" + XMLNS + "'>");
XMLStreamReader reader = xmlInputFactory.createXMLStreamReader(
new StringReader(xml));
return SiteDataStub.FPFolder.Factory.parse(reader);
}
}
}