/*
* This file is part of the Wayback archival access software
* (http://archive-access.sourceforge.net/projects/wayback/).
*
* Licensed to the Internet Archive (IA) by one or more individual
* contributors.
*
* The IA licenses this file to You 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 org.archive.wayback.accesspoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.archive.accesscontrol.AccessControlClient;
import org.archive.wayback.ResultURIConverter;
import org.archive.wayback.accesscontrol.CompositeExclusionFilterFactory;
import org.archive.wayback.accesscontrol.ExclusionFilterFactory;
import org.archive.wayback.accesscontrol.oracleclient.OracleExclusionFilterFactory;
import org.archive.wayback.accesscontrol.oracleclient.OraclePolicyService;
import org.archive.wayback.replay.html.ContextResultURIConverterFactory;
import org.archive.wayback.webapp.AccessPoint;
/**
*
* <p>
* 2014-11-06: {@code oracleUrl} property is removed. Use
* {@link OracleExclusionFilterFactory} instead.
* </p>
* <p>
* 2014-11-06: {@code staticExclusions} property is removed. Configure
* {@code exclusionFactory} property in Spring configuration with
* {@link CompositeExclusionFilterFactory}.
* </p>
*/
public class CompositeAccessPoint extends AccessPoint {
protected final static String REQUEST_CONTEXT_PREFIX = "webapp-request-context-path-prefix";
protected enum Status {
ConfigNotFound, ConfigHandled, ConfigNotHandled,
}
private HashMap<String, AccessPointAdapter> accessPointCache;
public CompositeAccessPoint() {
accessPointCache = new HashMap<String, AccessPointAdapter>();
}
@Override
public boolean handleRequest(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String configName = this.translateRequestPath(request);
if (!configName.isEmpty() && (configName.charAt(0) == '/')) {
configName = configName.substring(1);
}
int slash = configName.indexOf('/');
if (slash >= 0) {
configName = configName.substring(0, slash);
}
Object existingPrefixObj = request.getAttribute(REQUEST_CONTEXT_PREFIX);
String existingPrefix = (existingPrefixObj != null) ? existingPrefixObj
.toString() : "/";
request.setAttribute(REQUEST_CONTEXT_PREFIX, existingPrefix +
configName + "/");
Status status = handleRequest(configName, request, response);
return (status == Status.ConfigHandled);
}
protected Status handleRequest(String realAccessPoint,
HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// First, check cached accessPoint
AccessPointAdapter adapter = accessPointCache.get(realAccessPoint);
if ((adapter == null) && (accessPointConfigs != null)) {
AccessPointConfig config = accessPointConfigs
.getAccessPointConfigs().get(realAccessPoint);
if (config != null) {
adapter = new AccessPointAdapter(this, config);
accessPointCache.put(realAccessPoint, adapter);
}
}
if (adapter == null) {
return Status.ConfigNotFound;
}
boolean handled = adapter.handleRequest(request, response);
return (handled ? Status.ConfigHandled : Status.ConfigNotHandled);
}
// Refactoring: move uriConverterFactory and getUriConverterFactory() to
// AccessPoint, so that ResultURIConverter can be bootstrapped in a
// consistent manner.
private ContextResultURIConverterFactory uriConverterFactory;
public ContextResultURIConverterFactory getUriConverterFactory() {
return uriConverterFactory;
}
/**
* set {@link ContextResultURIConverterFactory} used for creating
* {@link ResultURIConverter} for each sub-{@code AccessPoint}.
* <p>
* it will receive default {@code replayURIPrefix} for sub-AccessPoint as
* {@code flags} argument.
* </p>
* @param uriConverterFactory
*/
public void setUriConverterFactory(
ContextResultURIConverterFactory uriConverterFactory) {
this.uriConverterFactory = uriConverterFactory;
}
private AccessPointConfigs accessPointConfigs;
public AccessPointConfigs getAccessPointConfigs() {
return accessPointConfigs;
}
public void setAccessPointConfigs(AccessPointConfigs accessPointConfigs) {
this.accessPointConfigs = accessPointConfigs;
}
public AccessPointConfig findConfigForFile(String file) {
for (AccessPointConfig config : accessPointConfigs
.getAccessPointConfigs().values()) {
for (String prefix : config.getFileIncludePrefixes()) {
if (file.startsWith(prefix)) {
return config;
}
}
}
return null;
}
// Overriden in ProxyAccessPoint when using proxy mode
public boolean isProxyEnabled() {
return false;
}
// deprecated members
private String oracleUrl;
private ArrayList<ExclusionFilterFactory> staticExclusions;
@Deprecated
public String getOracleUrl() {
return oracleUrl;
}
/**
* Service point URL for {@link AccessControlClient}
* @param oracleUrl URL
* @deprecated 2014-11-06 Use {@link OraclePolicyService}
*/
public void setOracleUrl(String oracleUrl) {
this.oracleUrl = oracleUrl;
}
@Deprecated
public ArrayList<ExclusionFilterFactory> getStaticExclusions() {
return staticExclusions;
}
/**
* Factories for static (collection independent) exclusion filters.
* @param staticExclusions list of exclusion filter factories
* @deprecated 2014-11-06 configure {@link AccessPoint#setExclusionFactory}
* using {@link CompositeExclusionFilterFactory}
*/
public void setStaticExclusions(
ArrayList<ExclusionFilterFactory> staticExclusions) {
this.staticExclusions = staticExclusions;
}
}