// 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.connector.util.filter; import com.google.common.base.Strings; import com.google.enterprise.connector.spi.Document; import com.google.enterprise.connector.spi.Principal; import com.google.enterprise.connector.spi.Property; import com.google.enterprise.connector.spi.RepositoryException; import com.google.enterprise.connector.spi.SimpleProperty; import com.google.enterprise.connector.spi.SpiConstants; import com.google.enterprise.connector.spi.SpiConstants.CaseSensitivityType; import com.google.enterprise.connector.spi.SpiConstants.PrincipalType; import com.google.enterprise.connector.spi.Value; import com.google.enterprise.connector.spiimpl.PrincipalValue; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; /** * A {@link Document} filter that forces the {@link CaseSensitivityType} field * for all ACL {@link com.google.enterprise.connector.spi.Principal Principals} * supplied by the connector to be set to a specified value. * <p> * This will over-ride any {@link CaseSensitivityType} that may have been set * by the connector, and supply one if none was set by the connector. * <p> * <b>Example {@code documentFilters.xml} Configurations:</b> * <p> * The following example forces all ACL Principals for all fed documents to be * considered case-insensitive. * <pre><code> <!-- Force case-insensitive ACLs. --> <bean id="CaseInsensitiveACLs" class="com.google.enterprise.connector.util.filter.AclPropertyFilter"> <property name="caseSensitivityType" value="everything-case-insensitive"/> </bean> </code></pre> * * @since 3.0 */ public class AclPropertyFilter extends AbstractDocumentFilter { /** The logger for this class. */ private static final Logger LOGGER = Logger.getLogger( AclPropertyFilter.class.getName()); /** Case sensitivity type flag. */ protected CaseSensitivityType caseSensitivityType; /** user domain. */ protected String userDomain; protected boolean overwriteUserDomain = false; private static final Set<String> aclUsers; private static final Set<String> aclUsersGroups; static { aclUsers = new HashSet<String>(); aclUsers.add(SpiConstants.PROPNAME_ACLUSERS); aclUsers.add(SpiConstants.PROPNAME_ACLDENYUSERS); aclUsersGroups = new HashSet<String>(); aclUsersGroups.add(SpiConstants.PROPNAME_ACLUSERS); aclUsersGroups.add(SpiConstants.PROPNAME_ACLDENYUSERS); aclUsersGroups.add(SpiConstants.PROPNAME_ACLGROUPS); aclUsersGroups.add(SpiConstants.PROPNAME_ACLDENYGROUPS); } /** * Sets the {@link CaseSensitivityType} to be used for all ACL * {@link com.google.enterprise.connector.spi.Principal Principals} * supplied by the connector. * * @param caseSensitivityType a String representation of a * {@link CaseSensitivityType}; i.e. {@code everything-case-sensitive} * or {@code everything-case-insensitive}. */ public void setCaseSensitivityType(String caseSensitivityType) { if (caseSensitivityType.equalsIgnoreCase( CaseSensitivityType.EVERYTHING_CASE_INSENSITIVE.toString())) { this.caseSensitivityType = CaseSensitivityType.EVERYTHING_CASE_INSENSITIVE; } else if (caseSensitivityType.equalsIgnoreCase( CaseSensitivityType.EVERYTHING_CASE_SENSITIVE.toString())) { this.caseSensitivityType = CaseSensitivityType.EVERYTHING_CASE_SENSITIVE; } } /** * Sets the domain for users for ACL Principals. * * @param userDomain the domain name to set for user principals. * @since 3.0.8 */ public void setUserDomain(String userDomain) { this.userDomain = Strings.emptyToNull(userDomain); } /** * Sets the overwrite value flag. * * @param overwriteUserDomain the overwrite flag. Overwrites the existing * domain values if true, or preserves existing domain values * if false. * @since 3.0.8 */ public void setOverwriteUserDomain(boolean overwriteUserDomain) { this.overwriteUserDomain = overwriteUserDomain; } /** * Finds a {@link Property} by {@code name}. If the requested property is * ACL property, then checks for case sensitivity type and modifies the value * if different than specified in filter. Returns ACL property with modified * values. * <p> */ @Override public Property findProperty(Document source, String name) throws RepositoryException { if (caseSensitivityType == null && userDomain == null) { return source.findProperty(name); } if (aclUsersGroups.contains(name)) { List<Value> values = super.getPropertyValues(source, name); ArrayList<Value> newValues = new ArrayList<Value>(values.size()); for (Value value : values) { Principal principal = (value instanceof PrincipalValue) ? ((PrincipalValue) value).getPrincipal() : new Principal(value.toString().trim()); if (caseSensitivityType != null && principal.getCaseSensitivityType() != caseSensitivityType) { if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.finest("Changing " + principal.getName() + " caseSensitivityType to " + caseSensitivityType); } Principal newPrincipal = new Principal(principal.getPrincipalType(), principal.getNamespace(), getPrincipalName(principal, name), caseSensitivityType); newValues.add(new PrincipalValue(newPrincipal)); } else { Principal newPrincipal = new Principal(principal.getPrincipalType(), principal.getNamespace(), getPrincipalName(principal, name), principal.getCaseSensitivityType()); newValues.add(new PrincipalValue(newPrincipal)); } } return new SimpleProperty(newValues); } else { return source.findProperty(name); } } private String getPrincipalName(Principal principal, String name) { String principalName = principal.getName(); if (aclUsers.contains(name)) { if (userDomain == null || principal.getPrincipalType() == PrincipalType.UNQUALIFIED) { return principalName; } else { String userName; if (principalName.contains("\\")) { userName = principalName.substring(principalName.indexOf("\\") + 1); } else if (principalName.contains("@")) { userName = principalName.substring(0, principalName.indexOf("@")); } else { userName = principalName; } if (overwriteUserDomain) { return userDomain + "\\" + userName; } else if (principalName.contains("\\")) { return principalName; } else { return userDomain + "\\" + userName; } } } else { return principalName; } } }