Added HelloWorldConnector Example
diff --git a/src/com/google/enterprise/adaptor/examples/helloworldconnector/HelloWorldAuthenticator.java b/src/com/google/enterprise/adaptor/examples/helloworldconnector/HelloWorldAuthenticator.java
new file mode 100644
index 0000000..ad19c78
--- /dev/null
+++ b/src/com/google/enterprise/adaptor/examples/helloworldconnector/HelloWorldAuthenticator.java
@@ -0,0 +1,176 @@
+package com.google.enterprise.adaptor.examples.helloworldconnector;
+
+// Copyright 2014 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.
+
+import com.google.enterprise.adaptor.AdaptorContext;
+import com.google.enterprise.adaptor.AuthnAuthority;
+import com.google.enterprise.adaptor.AuthnIdentity;
+import com.google.enterprise.adaptor.AuthzAuthority;
+import com.google.enterprise.adaptor.AuthzStatus;
+import com.google.enterprise.adaptor.DocId;
+import com.google.enterprise.adaptor.Session;
+
+import com.sun.net.httpserver.Headers;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.logging.Logger;
+
+/**
+ * Simple AuthN/AuthZ implementation
+ */
+class HelloWorldAuthenticator implements AuthnAuthority, AuthzAuthority,
+ HttpHandler {
+
+ private static final Logger log =
+ Logger.getLogger(HelloWorldAuthenticator.class.getName());
+
+ private AdaptorContext context;
+ private Callback callback;
+
+ public HelloWorldAuthenticator(AdaptorContext adaptorContext) {
+ if (adaptorContext == null) {
+ throw new NullPointerException();
+ }
+ context = adaptorContext;
+ }
+
+ @Override
+ public void authenticateUser(HttpExchange exchange, Callback callback)
+ throws IOException {
+
+ log.entering("HelloWorldAuthenticator", "authenticateUser");
+ context.getUserSession(exchange, true).setAttribute("callback",
+ callback);
+
+ Headers responseHeaders = exchange.getResponseHeaders();
+ responseHeaders.set("Content-Type", "text/html");
+ exchange.sendResponseHeaders(200, 0);
+ OutputStream os = exchange.getResponseBody();
+ String str = "<html><body><form action=\"/google-response\" method=Get>"
+ + "<input type=text name=userid/>"
+ + "<input type=password name=password/>"
+ + "<input type=submit value=submit></form></body></html>";
+ os.write(str.getBytes());
+ os.flush();
+ os.close();
+ exchange.close();
+ }
+
+ @Override
+ public Map<DocId, AuthzStatus> isUserAuthorized(AuthnIdentity userIdentity,
+ Collection<DocId> ids) throws IOException {
+
+ HashMap<DocId, AuthzStatus> authorizedDocs =
+ new HashMap<DocId, AuthzStatus>();
+
+ for (Iterator<DocId> iterator = ids.iterator(); iterator.hasNext();) {
+ DocId docId = iterator.next();
+ // if authorized
+ authorizedDocs.put(docId, AuthzStatus.PERMIT);
+ }
+ return authorizedDocs;
+ }
+
+ /**
+ * Handle the form submit from /samlip<br>
+ * If all goes well, this should result in an Authenticated user for the
+ * session
+ */
+ @Override
+ public void handle(HttpExchange ex) throws IOException {
+ log.entering("HelloWorldAuthenticator", "handle");
+
+ callback = getCallback(ex);
+ if (callback == null) {
+ return;
+ }
+
+ Map<String, String> parameters =
+ extractQueryParams(ex.getRequestURI().toString());
+ if (parameters.size() == 0 || null == parameters.get("userid")) {
+ log.warning("missing userid");
+ callback.userAuthenticated(ex, null);
+ return;
+ }
+ String userid = parameters.get("userid");
+ SimpleAuthnIdentity identity = new SimpleAuthnIdentity(userid);
+ callback.userAuthenticated(ex, identity);
+ }
+
+ // Return a 200 with simple response in body
+ private void sendResponseMessage(String message, HttpExchange ex)
+ throws IOException {
+ OutputStream os = ex.getResponseBody();
+ ex.sendResponseHeaders(200, 0);
+ os.write(message.getBytes());
+ os.flush();
+ os.close();
+ ex.close();
+ }
+
+ // Return the Callback method,
+ // or print error if the handler wasn't called correctly
+ private Callback getCallback(HttpExchange ex) throws IOException {
+ Session session = context.getUserSession(ex, false);
+ if (session == null) {
+ log.warning("No Session");
+ sendResponseMessage("No Session", ex);
+ return null;
+ }
+ Callback callback = (Callback) session.getAttribute("callback");
+ if (callback == null) {
+ log.warning("Something is wrong, callback object is missing");
+ sendResponseMessage("No Callback Specified", ex);
+ }
+ return callback;
+ }
+
+ // Parse user/password/group params
+ private Map<String, String> extractQueryParams(String request) {
+ Map<String, String> paramMap = new HashMap<String, String>();
+ int queryIndex = request.lastIndexOf("?");
+
+ if (queryIndex == -1) {
+ return paramMap;
+ }
+ String query = request.substring(queryIndex + 1);
+ String params[] = query.split("&", 4);
+ if (query.equals("")) {
+ return paramMap;
+ }
+ try {
+ for (int i = 0; i < params.length; ++i) {
+ String param[] = params[i].split("%2F=", 2);
+ paramMap.put(URLDecoder.decode(param[0], "UTF-8"),
+ URLDecoder.decode(param[1], "UTF-8"));
+ }
+ } catch (UnsupportedEncodingException e) {
+ log.warning("Request parameters may not have been properly encoded: "
+ + e.getMessage());
+ } catch (ArrayIndexOutOfBoundsException e) {
+ log.warning("Wrong number of parameters specified: " + e.getMessage());
+ }
+ return paramMap;
+ }
+}
diff --git a/src/com/google/enterprise/adaptor/examples/helloworldconnector/HelloWorldConnector.java b/src/com/google/enterprise/adaptor/examples/helloworldconnector/HelloWorldConnector.java
new file mode 100644
index 0000000..4b92538
--- /dev/null
+++ b/src/com/google/enterprise/adaptor/examples/helloworldconnector/HelloWorldConnector.java
@@ -0,0 +1,271 @@
+package com.google.enterprise.adaptor.examples.helloworldconnector;
+
+// Copyright 2014 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.
+
+import com.google.enterprise.adaptor.AbstractAdaptor;
+import com.google.enterprise.adaptor.Acl;
+import com.google.enterprise.adaptor.AdaptorContext;
+import com.google.enterprise.adaptor.DocId;
+import com.google.enterprise.adaptor.DocIdPusher;
+import com.google.enterprise.adaptor.GroupPrincipal;
+import com.google.enterprise.adaptor.PollingIncrementalLister;
+import com.google.enterprise.adaptor.Principal;
+import com.google.enterprise.adaptor.Request;
+import com.google.enterprise.adaptor.Response;
+import com.google.enterprise.adaptor.UserPrincipal;
+
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.logging.Logger;
+
+/**
+ * Demonstrates what code is necessary for putting content onto a GSA.
+ * The key operations are:
+ * <ol>
+ * <li>providing document ids either by Lister or Graph Traversal
+ * <li>providing document bytes and metadata given a document id
+ * </ol>
+ */
+public class HelloWorldConnector extends AbstractAdaptor implements
+ PollingIncrementalLister {
+
+ private static final Logger log =
+ Logger.getLogger(HelloWorldConnector.class.getName());
+ private boolean provideBodyOfDoc1003 = true;
+
+ @Override
+ public void init(AdaptorContext context) throws Exception {
+ context.setPollingIncrementalLister(this);
+ HelloWorldAuthenticator authenticator =
+ new HelloWorldAuthenticator(context);
+ context.setAuthnAuthority(authenticator);
+ context.setAuthzAuthority(authenticator);
+ context.createHttpContext("/google-response", authenticator);
+ }
+
+ /**
+ * This example shows how to use both the Lister & Graph Traversal.
+ * The root document ("") is a virtual doc which will contain a list of
+ * links to other docs when returned by the Retriever.
+ * If you aren't using Graph Traversal, all docids would be pushed in
+ * here, like 1001 and 1002 are.
+ */
+ @Override
+ public void getDocIds(DocIdPusher pusher) throws InterruptedException {
+ log.entering("HelloWorldConnector", "getDocIds");
+ ArrayList<DocId> mockDocIds = new ArrayList<DocId>();
+ // push docids
+ mockDocIds.add(new DocId(""));
+ mockDocIds.add(new DocId("1001"));
+ mockDocIds.add(new DocId("1002"));
+ pusher.pushDocIds(mockDocIds);
+ // push records
+ DocIdPusher.Record record = new DocIdPusher.Record.Builder(new DocId(
+ "1009")).setCrawlImmediately(true).setLastModified(new Date())
+ .build();
+ pusher.pushRecords(Collections.singleton(record));
+ // push named resources
+ HashMap<DocId, Acl> aclParent = new HashMap<DocId, Acl>();
+ ArrayList<Principal> permits = new ArrayList<Principal>();
+ permits.add(new UserPrincipal("user1", "Default"));
+ aclParent.put(new DocId("fakeID"), new Acl.Builder()
+ .setEverythingCaseInsensitive().setPermits(permits)
+ .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
+ .build());
+ pusher.pushNamedResources(aclParent);
+ }
+
+ /** Gives the bytes of a document referenced with id. */
+ @Override
+ public void getDocContent(Request req, Response resp) throws IOException {
+ log.entering("HelloWorldConnector", "getDocContent");
+ DocId id = req.getDocId();
+ log.info("DocId '" + id.getUniqueId() + "'");
+
+ // Hard-coded list of our doc ids
+ if ("".equals(id.getUniqueId())) {
+ // this is a the root folder, write some URLs
+ Writer writer = new OutputStreamWriter(resp.getOutputStream());
+ writer.write("<!DOCTYPE html>\n<html><body>");
+ writer.write("<br></br>");
+ writer.write("<a href=\"1001\">doc_not_changed</a>");
+ writer.write("<br></b r>");
+ writer.write("<a href=\"1002\">doc_changed</a>");
+ writer.write("<br></br>");
+ writer.write("<a href=\"1003\">doc_deleted</a>");
+ writer.write("<br></br>");
+ writer.write("<a href=\"1004\">doc_with_meta</a>");
+ writer.write("<br></br>");
+ writer.write("<a href=\"1005\">doc_with_ACL</a>");
+ writer.write("<br></br>");
+ writer.write("<a href=\"1006\">doc_with_ACL_Inheritance</a>");
+ writer.write("<br></br>");
+ writer.write("<a href=\"1007\">doc_with_Fragment</a>");
+ writer.write("<br></br>");
+ writer.write("<a href=\"1008\">doc_with_Fragment</a>");
+ writer.write("<br></br>");
+ writer.write("</body></html>");
+ writer.close();
+ } else if ("1001".equals(id.getUniqueId())) {
+ // Example with If-Modified-Since
+ // Set lastModifiedDate to 10 minutes ago
+ Date lastModifiedDate = new Date(System.currentTimeMillis() - 600000);
+ if (req.hasChangedSinceLastAccess(lastModifiedDate)) {
+ if (req.getLastAccessTime() == null) {
+ log.info("Requested docid 1001 with No If-Modified-Since");
+ } else {
+ log.info("Requested docid 1001 with If-Modified-Since < 10 minutes");
+ }
+ resp.setLastModified(new Date());
+ Writer writer = new OutputStreamWriter(resp.getOutputStream());
+ writer.write("Menu 1001 says latte");
+ writer.close();
+ } else {
+ log.info("Docid 1001 Not Modified");
+ resp.respondNotModified();
+ }
+ } else if ("1002".equals(id.getUniqueId())) {
+ // Very basic doc
+ Writer writer = new OutputStreamWriter(resp.getOutputStream());
+ writer.write("Menu 1002 says cappuccino");
+ writer.close();
+ } else if ("1003".equals(id.getUniqueId())) {
+ // Alternate between doc and a 404 response
+ if (provideBodyOfDoc1003) {
+ Writer writer = new OutputStreamWriter(resp.getOutputStream());
+ writer.write("Menu 1003 says machiato");
+ writer.close();
+ } else {
+ resp.respondNotFound();
+ }
+ provideBodyOfDoc1003 = !provideBodyOfDoc1003;
+ } else if ("1004".equals(id.getUniqueId())) {
+ // doc with metdata & different display URL
+ resp.addMetadata("flavor", "vanilla");
+ resp.addMetadata("flavor", "hazel nuts");
+ resp.addMetadata("taste", "strawberry");
+
+ try {
+ resp.setDisplayUrl(new URI("http://fake.com/a"));
+ } catch (URISyntaxException e) {
+ log.info(e.getMessage());
+ }
+ Writer writer = new OutputStreamWriter(resp.getOutputStream());
+ writer.write("Menu 1004 says espresso");
+ writer.close();
+ } else if ("1005".equals(id.getUniqueId())) {
+ // doc with ACLs
+ ArrayList<Principal> permits = new ArrayList<Principal>();
+ permits.add(new UserPrincipal("user1", "Default"));
+ permits.add(new UserPrincipal("eric", "Default"));
+ permits.add(new GroupPrincipal("group1", "Default"));
+ ArrayList<Principal> denies = new ArrayList<Principal>();
+ denies.add(new UserPrincipal("user2", "Default"));
+ denies.add(new GroupPrincipal("group2", "Default"));
+
+ resp.setAcl(new Acl.Builder()
+ .setEverythingCaseInsensitive()
+ .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
+ .setPermits(permits).setDenies(denies).build());
+
+ Writer writer = new OutputStreamWriter(resp.getOutputStream());
+ writer.write("Menu 1005 says americano");
+ writer.close();
+ } else if ("1006".equals(id.getUniqueId())) {
+ // Inherit ACLs from 1005
+ ArrayList<Principal> permits = new ArrayList<Principal>();
+ permits.add(new GroupPrincipal("group3", "Default"));
+ ArrayList<Principal> denies = new ArrayList<Principal>();
+ denies.add(new GroupPrincipal("group3", "Default"));
+
+ resp.setAcl(new Acl.Builder()
+ .setEverythingCaseInsensitive()
+ .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
+ .setInheritFrom(new DocId("1005")).setPermits(permits)
+ .setDenies(denies).build());
+
+ Writer writer = new OutputStreamWriter(resp.getOutputStream());
+ writer.write("Menu 1006 says misto");
+ writer.close();
+ } else if ("1007".equals(id.getUniqueId())) {
+ // Inherit ACLs from 1005 & 1006
+ ArrayList<Principal> permits = new ArrayList<Principal>();
+ permits.add(new GroupPrincipal("group5", "Default"));
+
+ resp.putNamedResource("Whatever", new Acl.Builder()
+ .setEverythingCaseInsensitive()
+ .setInheritFrom(new DocId("1006"))
+ .setPermits(permits)
+ .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
+ .build());
+
+ ArrayList<Principal> permits2 = new ArrayList<Principal>();
+ permits2.add(new GroupPrincipal("group4", "Default"));
+ ArrayList<Principal> denies = new ArrayList<Principal>();
+ denies.add(new GroupPrincipal("group4", "Default"));
+
+ resp.setAcl(new Acl.Builder()
+ .setEverythingCaseInsensitive()
+ .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
+ .setInheritFrom(new DocId("1005")).setPermits(permits2)
+ .setDenies(denies).build());
+
+ Writer writer = new OutputStreamWriter(resp.getOutputStream());
+ writer.write("Menu 1007 says frappuccino");
+ writer.close();
+ } else if ("1008".equals(id.getUniqueId())) {
+ // Inherit ACLs from 1007
+ ArrayList<Principal> denies = new ArrayList<Principal>();
+ denies.add(new GroupPrincipal("group5", "Default"));
+
+ resp.setAcl(new Acl.Builder()
+ .setEverythingCaseInsensitive()
+ .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
+ .setInheritFrom(new DocId("1007"), "Whatever")
+ .setDenies(denies).build());
+ Writer writer = new OutputStreamWriter(resp.getOutputStream());
+ writer.write("Menu 1008 says coffee");
+ writer.close();
+ } else if ("1009".equals(id.getUniqueId())) {
+ // Late Binding (security handled by connector)
+ resp.setSecure(true);
+ Writer writer = new OutputStreamWriter(resp.getOutputStream());
+ writer.write("Menu 1009 says espresso");
+ writer.close();
+ } else {
+ resp.respondNotFound();
+ }
+ }
+
+ @Override
+ public void getModifiedDocIds(DocIdPusher pusher) throws IOException,
+ InterruptedException {
+ ArrayList<DocId> mockDocIds = new ArrayList<DocId>();
+ mockDocIds.add(new DocId("1002"));
+ pusher.pushDocIds(mockDocIds);
+ }
+
+ /** Call default main for adaptors. */
+ public static void main(String[] args) {
+ AbstractAdaptor.main(new HelloWorldConnector(), args);
+ }
+}
diff --git a/src/com/google/enterprise/adaptor/examples/helloworldconnector/MetadataAddition.java b/src/com/google/enterprise/adaptor/examples/helloworldconnector/MetadataAddition.java
new file mode 100644
index 0000000..e9980ac
--- /dev/null
+++ b/src/com/google/enterprise/adaptor/examples/helloworldconnector/MetadataAddition.java
@@ -0,0 +1,91 @@
+package com.google.enterprise.adaptor.examples.helloworldconnector;
+
+// Copyright 2014 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.
+
+import com.google.enterprise.adaptor.DocumentTransform;
+import com.google.enterprise.adaptor.Metadata;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Example transform which will add values to metadata key "taste" if the
+ * document already has existing metdata key "taste"
+ * <p>
+ * A simple transformation can be added to the adaptor-config.properties file.
+ * This example combines "Mango" and "peach" with any existing "taste"
+ * metadata. If the document does not have a meta taste key, no values will
+ * be added.
+ * <p>
+ * <code>
+ * transform.pipeline=step1<br>
+ * transform.pipeline.step1.taste=Mango,peach<br>
+ * transform.pipeline.step1.factoryMethod=com.google.enterprise.adaptor.examples.HelloWorldConnector.MetadataAddition.load<br>
+ * </code>
+ * <p>
+ */
+
+public class MetadataAddition implements DocumentTransform {
+ private static final Logger log = Logger.getLogger(MetadataAddition.class
+ .getName());
+ private static final String META_TASTE = "taste";
+ private Set<String> valuesToAdd = null;
+
+ private MetadataAddition(String values) {
+ if (null == values) {
+ throw new NullPointerException();
+ }
+ String valueArray[] = values.split(",", 0);
+ valuesToAdd = new HashSet<String>(Arrays.asList(valueArray));
+ }
+
+ /**
+ * Called as <code>transfordm.pipeline.<stepX>.factoryMethod for this
+ * transformation pipline as specified in adaptor-config.properties.
+ * <p>
+ * This method simply returns a new object with the additional
+ * metadata as specified as values for step1.taste
+ */
+ public static MetadataAddition load(Map<String, String> cfg) {
+ return new MetadataAddition(cfg.get(META_TASTE));
+ }
+
+ /**
+ * Here we check to see if the current doc contains a "taste" key
+ * and if so, add the additional values from the config file
+ */
+ @Override
+ public void transform(Metadata metadata, Map<String, String> params) {
+ Set<String> values = metadata.getAllValues(META_TASTE);
+ if (values.isEmpty()) {
+ log.log(Level.INFO, "no metadata {0}. Skipping", META_TASTE);
+ } else {
+ log.log(Level.INFO,
+ "adding values {1} for existing metadata {0} ",
+ new Object[] { META_TASTE, valuesToAdd });
+ metadata.set(META_TASTE, combine(values, valuesToAdd));
+ }
+ }
+
+ private Set<String> combine(Set<String> s1, Set<String> s2) {
+ Set<String> combined = new HashSet<String>(s1);
+ combined.addAll(s2);
+ return combined;
+ }
+}
diff --git a/src/com/google/enterprise/adaptor/examples/helloworldconnector/SimpleAuthnIdentity.java b/src/com/google/enterprise/adaptor/examples/helloworldconnector/SimpleAuthnIdentity.java
new file mode 100644
index 0000000..14a6f3c
--- /dev/null
+++ b/src/com/google/enterprise/adaptor/examples/helloworldconnector/SimpleAuthnIdentity.java
@@ -0,0 +1,85 @@
+package com.google.enterprise.adaptor.examples.helloworldconnector;
+
+// Copyright 2014 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.
+
+import com.google.enterprise.adaptor.AuthnIdentity;
+import com.google.enterprise.adaptor.GroupPrincipal;
+import com.google.enterprise.adaptor.UserPrincipal;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Simple implementation of AuthnIdentity
+ */
+class SimpleAuthnIdentity implements AuthnIdentity {
+
+ private UserPrincipal user;
+ private Set<GroupPrincipal> groups;
+
+ public SimpleAuthnIdentity(String uid) throws NullPointerException {
+ if (uid == null) {
+ throw new NullPointerException("Null user not allowed");
+ }
+ this.user = new UserPrincipal(uid);
+ }
+
+ //Constructor with user & single group
+ public SimpleAuthnIdentity(String uid, String gid)
+ throws NullPointerException {
+ this(uid);
+ this.groups = new TreeSet<GroupPrincipal>();
+ if (gid != null && !"".equals(gid)) {
+ this.groups.addAll(Collections.singleton(new GroupPrincipal(gid)));
+ }
+ this.groups =
+ Collections.unmodifiableSet(this.groups);
+ }
+
+ // Constructor with user & groups
+ public SimpleAuthnIdentity(String uid, Collection<String> gids)
+ throws NullPointerException {
+ this(uid);
+ this.groups = new TreeSet<GroupPrincipal>();
+ for (String n : gids) {
+ if (n != null && !"".equals(n)) {
+ this.groups.addAll(Collections.singleton(new GroupPrincipal(n)));
+ }
+ }
+ this.groups =
+ Collections.unmodifiableSet(this.groups);
+ }
+
+ @Override
+ public UserPrincipal getUser() {
+ return user;
+ }
+
+ /**
+ * Returns null in this example since we don't do anything with the
+ * password, but getPassword() must be implemented for AuthnIdentity
+ */
+ @Override
+ public String getPassword() {
+ return null;
+ }
+
+ @Override
+ public Set<GroupPrincipal> getGroups() {
+ return groups;
+ }
+}