Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.marklogic.xcc.impl.ContentSourceImpl Maven / Gradle / Ivy
/*
* Copyright (c) 2024 MarkLogic Corporation
*
* 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.marklogic.xcc.impl;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import com.marklogic.http.HttpChannel;
import com.marklogic.xcc.ContentSource;
import com.marklogic.xcc.Session;
import com.marklogic.xcc.UserCredentials;
import com.marklogic.xcc.spi.ConnectionProvider;
@SuppressWarnings("deprecation")
public class ContentSourceImpl implements ContentSource {
public static enum AuthType {
NONE, BASIC, DIGEST, NEGOTIATE, MLCLOUD, OAUTH
};
private static final String DEFAULT_LOGGER_NAME = "com.marklogic.xcc";
private static final String XCC_LOGGING_CONFIG_FILE = "xcc.logging.properties";
private static final String XCC_CONFIG_FILE = "xcc.properties";
private static final String SYSTEM_LOGGING_CONFIG_CLASS = "java.util.logging.config.class";
private static final String SYSTEM_LOGGING_CONFIG_FILE = "java.util.logging.config.file";
private final ConnectionProvider connectionProvider;
private final String contentBase;
private final String basePath;
private boolean authenticationPreemptive = false;
private boolean challengeIgnored = false; // for regression testing only
/**
* logger is initiated before initializeConfig()
*/
private Logger logger = newDefaultLogger();
private AuthType authType = AuthType.NONE;
private String challenge;
private Credentials credentials;
private static MLCloudAuthManager mlCloudAuthManager;
private static Logger newDefaultLogger() {
LogManager logManager = LogManager.getLogManager();
Logger logger = logManager.getLogger(DEFAULT_LOGGER_NAME);
if (logger != null) {
return logger;
}
if ((System.getProperty(SYSTEM_LOGGING_CONFIG_CLASS) != null)
|| (System.getProperty(SYSTEM_LOGGING_CONFIG_FILE) != null)) {
// If custom config file or class, don't override anything
return Logger.getLogger(DEFAULT_LOGGER_NAME);
}
return customizedLogger(logManager);
}
private void initializeConfig() {
URL url = getClass().getClassLoader().getResource(XCC_CONFIG_FILE);
Properties props = System.getProperties();
if (url != null) {
try (FileInputStream is = new FileInputStream(url.getPath())) {
props.load(is);
} catch (IOException e) {
logger.log(Level.WARNING,
"property file not found:" + url.getPath());
}
}
}
public ContentSourceImpl(ConnectionProvider connectionProvider,
char[] OAuthToken, String contentBase,
String basePath) {
this(connectionProvider, new Credentials(OAuthToken), contentBase,
basePath);
}
public ContentSourceImpl(ConnectionProvider connectionProvider, String user,
char[] password, String contentBase) {
this(connectionProvider, new Credentials(user, password), contentBase,
null);
}
public ContentSourceImpl(ConnectionProvider connectionProvider, String user,
char[] password, String contentBase,
String basePath) {
this(connectionProvider, new Credentials(user, password), contentBase,
basePath);
}
public ContentSourceImpl(ConnectionProvider connectionProvider,
char[] apiKey, String contentBase, String basePath,
String tokenEndpoint, String grantType,
int tokenDuration) {
this(connectionProvider,
new Credentials(apiKey, tokenEndpoint, grantType, tokenDuration),
contentBase, basePath);
}
public ContentSourceImpl(ConnectionProvider connectionProvider,
Credentials credentials, String contentBase,
String basePath) {
this.connectionProvider = connectionProvider;
this.credentials = credentials;
String cbName = contentBase;
this.basePath = basePath;
if (cbName != null) {
cbName = cbName.trim();
if (cbName.length() == 0) {
cbName = null;
}
}
this.contentBase = cbName;
initializeConfig();
//For MLCloudAuth and OAuth, different from the flow that xcc relies on
// ML server to set auth challenge by sending the first request to ML
// server and getting a 401 unauthorized, xcc needs the user to pass the
// tokens to figure out the auth type.
initTokenBasedAuth();
}
// Constructor for creating dedicated content source object for ML Cloud
private ContentSourceImpl(ConnectionProvider connectionProvider,
Credentials credentials, String basePath) {
this.connectionProvider = connectionProvider;
this.credentials = credentials;
this.basePath = basePath;
this.contentBase = null;
}
private void initTokenBasedAuth() {
if (credentials.getMLCloudAuthConfig() != null) {
setMLCloudAuthType();
HttpChannel.setUseHTTP(true);
MLCloudAuthManager.createMLCloudAuthContext(new ContentSourceImpl(
connectionProvider, credentials, basePath));
} else if (credentials.getOAuthToken() != null) {
setOAuthAuthType();
}
}
public ConnectionProvider getConnectionProvider() {
return connectionProvider;
}
public UserCredentials getUserCredentials() { return credentials; }
public Session newSession() {
return (new SessionImpl(
this, connectionProvider, credentials, contentBase, basePath));
}
public Session newSession(String userName, char[] password) {
return (new SessionImpl(this, connectionProvider,
new Credentials(userName, password), contentBase, basePath));
}
public Session newSession(String user, char[] password, String contentBaseArg) {
String contentBase = (contentBaseArg == null) ? this.contentBase : contentBaseArg;
return (new SessionImpl(this, connectionProvider,
new Credentials(user, password), contentBase, basePath));
}
public Session newSession(String databaseId) {
return (new SessionImpl(
this, connectionProvider, credentials, databaseId, basePath));
}
public Logger getDefaultLogger() {
return logger;
}
public void setDefaultLogger(Logger logger) {
this.logger = logger;
}
public boolean isAuthenticationPreemptive() {
return this.authenticationPreemptive;
}
public void setAuthenticationPreemptive(boolean value) {
this.authenticationPreemptive = value;
}
public void setAuthChallenge(String challenge) {
synchronized(this) {
this.authType = AuthType.valueOf(challenge.split(" ")[0].toUpperCase());
this.challenge = challenge;
}
}
public synchronized void setMLCloudAuthType() {
this.authType = AuthType.MLCLOUD;
}
public synchronized void setOAuthAuthType() {
this.authType = AuthType.OAUTH;
}
/**
* For regression testing only; returns whether session to ignore authentication challenges and fail immediately.
*/
public boolean isChallengeIgnored() {
return challengeIgnored;
}
/**
* For regression testing only; tells session to ignore authentication challenges and fail immediately.
*/
public void setChallengeIgnored(boolean challengeIgnored) {
this.challengeIgnored = challengeIgnored;
}
public String getAuthString(String method, String uri, UserCredentials credentials) {
AuthType authType;
String challenge;
synchronized(this) {
authType = this.authType;
challenge = this.challenge;
}
switch (authType) {
case BASIC:
return credentials.toHttpBasicAuth();
case DIGEST:
return credentials.toHttpDigestAuth(method, uri, challenge);
case NEGOTIATE:
return credentials.toHttpNegotiateAuth(connectionProvider.getHostName(), challenge);
case MLCLOUD:
return credentials.toMLCloudAuth();
case OAUTH:
return credentials.toOAuth();
default:
return isAuthenticationPreemptive() ? credentials.toHttpBasicAuth() : null;
}
}
@Override
public String toString() {
return "user=" + ((credentials.getUserName() == null) ?
"{none}" : credentials.getUserName()) +
", cb=" + ((contentBase == null) ? "{none}" : contentBase) +
" [provider: " + connectionProvider.toString() + "]";
}
// -------------------------------------------------------------
private static Logger customizedLogger(LogManager logManager) {
Properties props = loadLoggingPropertiesFromResource();
Logger logger = Logger.getLogger(DEFAULT_LOGGER_NAME);
List handlers = getLoggerHandlers(logger, logManager, props);
for (Iterator it = handlers.iterator(); it.hasNext();) {
logger.addHandler(it.next());
}
boolean useParentHandlers = getUseParentHandlersFlag(logger, logManager, props);
logger.setUseParentHandlers(useParentHandlers);
logManager.addLogger(logger);
return logger;
}
private static Properties loadLoggingPropertiesFromResource() {
Properties props = new Properties();
URL url = ClassLoader.getSystemResource(XCC_LOGGING_CONFIG_FILE);
if (url != null) {
try (FileInputStream is = new FileInputStream(url.getPath())) {
props.load(is);
return props;
} catch (IOException e) {
//property file not found
Logger logger = Logger.getLogger(DEFAULT_LOGGER_NAME);
if(logger!=null) {
logger.warning("property file not found: " + url);
}
}
}
// Load properties internally from com.marklogic.xcc package in
// xcc.jar
try (InputStream is =
ContentSource.class.getResourceAsStream(XCC_LOGGING_CONFIG_FILE)) {
if (is != null) {
props.load(is);
}
} catch (IOException e) {
// property file not found
Logger logger = Logger.getLogger(DEFAULT_LOGGER_NAME);
if (logger!=null) {
logger.warning("Error loading default logging file: " +
e.getMessage());
}
}
return props;
}
private static List getLoggerHandlers(Logger logger, LogManager logManager, Properties props) {
String propName = logger.getName() + ".handlers";
String handlerPropVal = getPropertyValue(propName, logManager, props);
if (handlerPropVal == null) {
return new ArrayList(0);
}
String[] handlerClassNames = handlerPropVal.split("\\\\s*,?\\\\s*");
List handlers = new ArrayList(handlerClassNames.length);
Level level = getLoggerLevel(logger, logManager, props);
if (level != null)
logger.setLevel(level);
for (int i = 0; i < handlerClassNames.length; i++) {
try {
Class extends Handler> handlerClass = Class.forName(handlerClassNames[i]).asSubclass(Handler.class);
Handler handler = handlerClass.newInstance();
Formatter formatter = getFormatter(handler, logManager, props);
handlers.add(handler);
if (formatter != null)
handler.setFormatter(formatter);
if (level != null)
handler.setLevel(level);
} catch (Exception e) {
// Do nothing, can't instantiate the handler class
}
}
return handlers;
}
private static Formatter getFormatter(Handler handler, LogManager logManager, Properties props) {
String propName = handler.getClass().getName() + ".formatter";
String formatterClassName = getPropertyValue(propName, logManager, props);
try {
Class extends Formatter> clazz = Class.forName(formatterClassName).asSubclass(Formatter.class);
Constructor extends Formatter> cons = null;
try {
cons = clazz.getConstructor(new Class[] { Properties.class, LogManager.class });
} catch (Exception e) {
// do nothing, may not be our LogFormatter class
}
if (cons != null) {
return cons.newInstance(new Object[] { props, logManager });
}
return (Formatter)Class.forName(formatterClassName).newInstance();
} catch (Exception e) {
return null;
}
}
private static Level getLoggerLevel(Logger logger, LogManager logManager, Properties props) {
String propName = logger.getName() + ".level";
String levelName = getPropertyValue(propName, logManager, props);
try {
return Level.parse(levelName);
} catch (Exception e) {
return null;
}
}
private static boolean getUseParentHandlersFlag(Logger logger, LogManager logManager, Properties props) {
String propName = logger.getName() + ".useParentHandlers";
String propValue = getPropertyValue(propName, logManager, props);
if (propValue == null) {
return false;
}
try {
return Boolean.valueOf(propValue).booleanValue();
} catch (Exception e) {
return false;
}
}
private static String getPropertyValue(String propName, LogManager logManager, Properties props) {
String propVal = props.getProperty(propName);
if (propVal != null) {
return propVal.trim();
}
propVal = logManager.getProperty(propName);
if (propVal != null) {
return propVal.trim();
}
return null;
}
// -------------------------------------------------------------
@Override
public Session newSession(String userName, String password) {
return newSession(userName,
password == null ? null : password.toCharArray());
}
@Override
public Session newSession(String userName, String password,
String contentbaseId) {
return newSession(userName,
password == null ? null : password.toCharArray(),
contentbaseId);
}
}