/*
* ====================
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of the Common Development
* and Distribution License("CDDL") (the "License"). You may not use this file
* except in compliance with the License.
*
* You can obtain a copy of the License at
* http://opensource.org/licenses/cddl1.php
* See the License for the specific language governing permissions and limitations
* under the License.
*
* When distributing the Covered Code, include this CDDL Header Notice in each file
* and include the License file at http://opensource.org/licenses/cddl1.php.
* If applicable, add the following below this CDDL Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
* ====================
* Portions Copyrighted 2010-2014 ForgeRock AS.
*/
package org.identityconnectors.framework.impl.api.local;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
import org.identityconnectors.framework.api.operations.APIOperation;
import org.identityconnectors.framework.api.operations.AuthenticationApiOp;
import org.identityconnectors.framework.api.operations.CreateApiOp;
import org.identityconnectors.framework.api.operations.DeleteApiOp;
import org.identityconnectors.framework.api.operations.GetApiOp;
import org.identityconnectors.framework.api.operations.ResolveUsernameApiOp;
import org.identityconnectors.framework.api.operations.SchemaApiOp;
import org.identityconnectors.framework.api.operations.ScriptOnConnectorApiOp;
import org.identityconnectors.framework.api.operations.ScriptOnResourceApiOp;
import org.identityconnectors.framework.api.operations.SearchApiOp;
import org.identityconnectors.framework.api.operations.SyncApiOp;
import org.identityconnectors.framework.api.operations.TestApiOp;
import org.identityconnectors.framework.api.operations.UpdateApiOp;
import org.identityconnectors.framework.api.operations.ValidateApiOp;
import org.identityconnectors.framework.common.exceptions.ConnectorException;
import org.identityconnectors.framework.impl.api.APIConfigurationImpl;
import org.identityconnectors.framework.impl.api.AbstractConnectorFacade;
import org.identityconnectors.framework.impl.api.LoggingProxy;
import org.identityconnectors.framework.impl.api.local.operations.APIOperationRunner;
import org.identityconnectors.framework.impl.api.local.operations.AuthenticationImpl;
import org.identityconnectors.framework.impl.api.local.operations.ConnectorAPIOperationRunner;
import org.identityconnectors.framework.impl.api.local.operations.ConnectorAPIOperationRunnerProxy;
import org.identityconnectors.framework.impl.api.local.operations.ConnectorOperationalContext;
import org.identityconnectors.framework.impl.api.local.operations.CreateImpl;
import org.identityconnectors.framework.impl.api.local.operations.DeleteImpl;
import org.identityconnectors.framework.impl.api.local.operations.GetImpl;
import org.identityconnectors.framework.impl.api.local.operations.OperationalContext;
import org.identityconnectors.framework.impl.api.local.operations.ResolveUsernameImpl;
import org.identityconnectors.framework.impl.api.local.operations.SchemaImpl;
import org.identityconnectors.framework.impl.api.local.operations.ScriptOnConnectorImpl;
import org.identityconnectors.framework.impl.api.local.operations.ScriptOnResourceImpl;
import org.identityconnectors.framework.impl.api.local.operations.SearchImpl;
import org.identityconnectors.framework.impl.api.local.operations.SyncImpl;
import org.identityconnectors.framework.impl.api.local.operations.TestImpl;
import org.identityconnectors.framework.impl.api.local.operations.ThreadClassLoaderManagerProxy;
import org.identityconnectors.framework.impl.api.local.operations.UpdateImpl;
import org.identityconnectors.framework.impl.api.local.operations.ValidateImpl;
import org.identityconnectors.framework.spi.Connector;
/**
* Implements all the methods of the facade.
* <p>
*/
public class LocalConnectorFacadeImpl extends AbstractConnectorFacade {
// =======================================================================
// Constants
// =======================================================================
/**
* Map the API interfaces to their implementation counterparts.
*/
private static final Map<Class<? extends APIOperation>, Constructor<? extends ConnectorAPIOperationRunner>> API_TO_IMPL =
new HashMap<Class<? extends APIOperation>, Constructor<? extends ConnectorAPIOperationRunner>>();
private static void addImplementation(final Class<? extends APIOperation> inter,
final Class<? extends ConnectorAPIOperationRunner> impl) {
Constructor<? extends ConnectorAPIOperationRunner> constructor;
try {
constructor = impl.getConstructor(ConnectorOperationalContext.class, Connector.class);
API_TO_IMPL.put(inter, constructor);
} catch (Exception e) {
// this should never happen..
throw ConnectorException.wrap(e);
}
}
static {
addImplementation(CreateApiOp.class, CreateImpl.class);
addImplementation(DeleteApiOp.class, DeleteImpl.class);
addImplementation(SchemaApiOp.class, SchemaImpl.class);
addImplementation(SearchApiOp.class, SearchImpl.class);
addImplementation(UpdateApiOp.class, UpdateImpl.class);
addImplementation(AuthenticationApiOp.class, AuthenticationImpl.class);
addImplementation(ResolveUsernameApiOp.class, ResolveUsernameImpl.class);
addImplementation(TestApiOp.class, TestImpl.class);
addImplementation(ScriptOnConnectorApiOp.class, ScriptOnConnectorImpl.class);
addImplementation(ScriptOnResourceApiOp.class, ScriptOnResourceImpl.class);
addImplementation(SyncApiOp.class, SyncImpl.class);
}
// =======================================================================
// Fields
// =======================================================================
/**
* The connector info
*/
private final LocalConnectorInfoImpl connectorInfo;
/**
* Shared OperationalContext for stateful facades
*/
private final ConnectorOperationalContext operationalContext;
/**
* Builds up the maps of supported operations and calls.
*/
public LocalConnectorFacadeImpl(final LocalConnectorInfoImpl connectorInfo,
final APIConfigurationImpl apiConfiguration) {
super(apiConfiguration);
this.connectorInfo = connectorInfo;
if (connectorInfo.isConfigurationStateless()
&& !connectorInfo.isConnectorPoolingSupported()) {
operationalContext = null;
} else {
operationalContext =
new ConnectorOperationalContext(connectorInfo, getAPIConfiguration());
}
}
public LocalConnectorFacadeImpl(final LocalConnectorInfoImpl connectorInfo, String configuration) {
super(configuration, connectorInfo);
this.connectorInfo = connectorInfo;
if (connectorInfo.isConfigurationStateless()
&& !connectorInfo.isConnectorPoolingSupported()) {
operationalContext = null;
} else {
operationalContext =
new ConnectorOperationalContext(connectorInfo, getAPIConfiguration());
}
}
public void dispose() {
if (null != operationalContext) {
operationalContext.dispose();
}
}
protected ConnectorOperationalContext getOperationalContext() {
if (null == operationalContext) {
return new ConnectorOperationalContext(connectorInfo, getAPIConfiguration());
}
return operationalContext;
}
// =======================================================================
// ConnectorFacade Interface
// =======================================================================
@Override
protected APIOperation getOperationImplementation(final Class<? extends APIOperation> api) {
APIOperation proxy;
// first create the inner proxy - this is the proxy that obtaining
// a connector from the pool, etc
// NOTE: we want to skip this part of the proxy for
// validate op, but we will want the timeout proxy
if (api == ValidateApiOp.class) {
final OperationalContext context =
new OperationalContext(connectorInfo, getAPIConfiguration());
proxy = new ValidateImpl(context);
} else if (api == GetApiOp.class) {
final Constructor<? extends APIOperationRunner> constructor =
API_TO_IMPL.get(SearchApiOp.class);
final ConnectorAPIOperationRunnerProxy handler =
new ConnectorAPIOperationRunnerProxy(getOperationalContext(), constructor);
proxy = new GetImpl((SearchApiOp) newAPIOperationProxy(SearchApiOp.class, handler));
} else {
final Constructor<? extends APIOperationRunner> constructor = API_TO_IMPL.get(api);
final ConnectorAPIOperationRunnerProxy handler =
new ConnectorAPIOperationRunnerProxy(getOperationalContext(), constructor);
proxy = newAPIOperationProxy(api, handler);
}
// now proxy to setup the thread-local classloader
proxy =
newAPIOperationProxy(api, new ThreadClassLoaderManagerProxy(connectorInfo
.getConnectorClass().getClassLoader(), proxy));
// now wrap the proxy in the appropriate timeout proxy
proxy = createTimeoutProxy(api, proxy);
// wrap in a logging proxy..
if (LoggingProxy.isLoggable()) {
proxy = createLoggingProxy(api, proxy);
}
return proxy;
}
}