/*
* DO NOT REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2012-2013 ForgeRock Inc. All rights reserved.
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://forgerock.org/license/CDDLv1.0.html
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at http://forgerock.org/license/CDDLv1.0.html
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*/
package org.forgerock.openicf.connectors.os400;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.util.Set;
import org.identityconnectors.common.logging.Log;
import org.identityconnectors.common.security.GuardedString;
import org.identityconnectors.framework.common.FrameworkUtil;
import org.identityconnectors.framework.common.exceptions.ConnectorException;
import org.identityconnectors.framework.common.exceptions.ConnectorIOException;
import org.identityconnectors.framework.common.exceptions.ConnectorSecurityException;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.AttributeInfoBuilder;
import org.identityconnectors.framework.common.objects.Name;
import org.identityconnectors.framework.common.objects.ObjectClass;
import org.identityconnectors.framework.common.objects.ObjectClassInfoBuilder;
import org.identityconnectors.framework.common.objects.OperationOptions;
import org.identityconnectors.framework.common.objects.OperationalAttributeInfos;
import org.identityconnectors.framework.common.objects.PredefinedAttributeInfos;
import org.identityconnectors.framework.common.objects.ResultsHandler;
import org.identityconnectors.framework.common.objects.Schema;
import org.identityconnectors.framework.common.objects.SchemaBuilder;
import org.identityconnectors.framework.common.objects.ScriptContext;
import org.identityconnectors.framework.common.objects.SyncResultsHandler;
import org.identityconnectors.framework.common.objects.SyncToken;
import org.identityconnectors.framework.common.objects.Uid;
import org.identityconnectors.framework.common.objects.filter.FilterTranslator;
import org.identityconnectors.framework.spi.Configuration;
import org.identityconnectors.framework.spi.Connector;
import org.identityconnectors.framework.spi.ConnectorClass;
import org.identityconnectors.framework.spi.PoolableConnector;
import org.identityconnectors.framework.spi.operations.AuthenticateOp;
import org.identityconnectors.framework.spi.operations.CreateOp;
import org.identityconnectors.framework.spi.operations.DeleteOp;
import org.identityconnectors.framework.spi.operations.ResolveUsernameOp;
import org.identityconnectors.framework.spi.operations.SchemaOp;
import org.identityconnectors.framework.spi.operations.ScriptOnConnectorOp;
import org.identityconnectors.framework.spi.operations.ScriptOnResourceOp;
import org.identityconnectors.framework.spi.operations.SearchOp;
import org.identityconnectors.framework.spi.operations.SyncOp;
import org.identityconnectors.framework.spi.operations.TestOp;
import org.identityconnectors.framework.spi.operations.UpdateAttributeValuesOp;
import com.ibm.as400.access.AS400;
import com.ibm.as400.access.AS400Message;
import com.ibm.as400.access.AS400SecurityException;
import com.ibm.as400.access.CommandCall;
import com.ibm.as400.access.RequestNotSupportedException;
import com.ibm.as400.access.SecureAS400;
import com.ibm.as400.access.SystemValue;
import com.ibm.as400.access.User;
/**
* Main implementation of the OS400 Connector.
*
*/
@ConnectorClass(displayNameKey = "OS400", configurationClass = OS400Configuration.class)
public class OS400Connector implements PoolableConnector, AuthenticateOp, ResolveUsernameOp,
CreateOp, DeleteOp, SchemaOp, ScriptOnConnectorOp, ScriptOnResourceOp, SearchOp<String>,
SyncOp, TestOp, UpdateAttributeValuesOp {
/**
* Setup logging for the {@link OS400Connector}.
*/
private static final Log LOG = Log.getLog(OS400Connector.class);
/**
* Place holder for the {@link Schema} create in the schema() method
* {@link OS400Connector#schema}.
*/
private Schema schema;
/**
* Place holder for the {@link Configuration} passed into the init() method
* {@link OS400Connector#init(org.identityconnectors.framework.spi.Configuration)}
* .
*/
private OS400Configuration configuration;
/**
* Place holder for the Connection created in the init method.
*/
private AS400 as400 = null;
private int passwordLevel = QPWDLVL_UNFETCHED;
public static final int QPWDLVL_UNFETCHED = -2;
public static final int QPWDLVL_UNSET = -1;
/**
* Gets the Configuration context for this connector.
*/
public Configuration getConfiguration() {
return this.configuration;
}
/**
* Callback method to receive the {@link Configuration}.
*
* @see Connector#init(org.identityconnectors.framework.spi.Configuration)
*/
public void init(Configuration configuration1) {
this.configuration = (OS400Configuration) configuration1;
if (as400 == null) {
try {
final StringBuilder clear = new StringBuilder();
GuardedString.Accessor accessor = new GuardedString.Accessor() {
public void access(char[] clearChars) {
clear.append(clearChars);
}
};
configuration.getPassword().access(accessor);
if (configuration.isSsl()) {
as400 =
new SecureAS400(configuration.getHost(), configuration.getRemoteUser(),
clear.toString());
} else {
as400 =
new AS400(configuration.getHost(), configuration.getRemoteUser(), clear
.toString());
}
clear.setLength(0);
if (as400 == null) {
throw new ConnectorException("Connection Exception");
}
if (!as400.validateSignon()) {
throw new ConnectorSecurityException("Login Error");
}
try {
as400.setGuiAvailable(false);
fetchPasswordLevel();
} catch (Exception e) {
}
} catch (AS400SecurityException e) {
throw new ConnectorSecurityException(e);
} catch (IOException e) {
throw new ConnectorIOException(e);
}
}
}
/**
* Disposes of the {@link OS400Connector}'s resources.
*
* @see Connector#dispose()
*/
public void dispose() {
configuration = null;
if (as400 != null) {
as400.disconnectAllServices();
as400 = null;
}
}
/**
* {@inheritDoc}
*/
public void checkAlive() {
if (null == as400 || !as400.isConnected()) {
throw new ConnectorException("Connection is not alive");
}
}
/******************
* SPI Operations
*
* Implement the following operations using the contract and description
* found in the Javadoc for these methods.
******************/
/**
* {@inheritDoc}
*/
public Uid authenticate(final ObjectClass objectClass, final String userName,
final GuardedString password, final OperationOptions options) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
public Uid resolveUsername(final ObjectClass objectClass, final String userName,
final OperationOptions options) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
public Uid create(final ObjectClass objectClass, final Set<Attribute> createAttributes,
final OperationOptions options) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
public void delete(final ObjectClass objectClass, final Uid uid, final OperationOptions options) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
public Schema schema() {
if (null == schema) {
SchemaBuilder schemaBuilder = new SchemaBuilder(getClass());
// Users
ObjectClassInfoBuilder ocBuilder = new ObjectClassInfoBuilder();
ocBuilder.setType(ObjectClass.ACCOUNT_NAME);
// The name of the object
ocBuilder.addAttributeInfo(Name.INFO);
// ocBuilder.addAttributeInfo(AttributeInfoBuilder.build(Name.NAME,
// String.class, EnumSet.of(AttributeInfo.Flags.REQUIRED,
// AttributeInfo.Flags.NOT_UPDATEABLE)));
// User registry name
// ocBuilder.addAttributeInfo(AttributeInfoBuilder.build(ATTR_FIRST_NAME,
// String.class, EnumSet.of(AttributeInfo.Flags.NOT_UPDATEABLE)));
try {
BeanInfo info = Introspector.getBeanInfo(User.class);
for (PropertyDescriptor propertyDescriptor : info.getPropertyDescriptors()) {
if (FrameworkUtil
.isSupportedAttributeType(propertyDescriptor.getPropertyType())) {
ocBuilder.addAttributeInfo(AttributeInfoBuilder.build(propertyDescriptor
.getName(), propertyDescriptor.getPropertyType()));
}
}
} catch (IntrospectionException e) {
}
ocBuilder.addAttributeInfo(PredefinedAttributeInfos.DESCRIPTION);
ocBuilder.addAttributeInfo(PredefinedAttributeInfos.LAST_LOGIN_DATE);
ocBuilder.addAttributeInfo(PredefinedAttributeInfos.GROUPS);
ocBuilder.addAttributeInfo(OperationalAttributeInfos.PASSWORD);
ocBuilder.addAttributeInfo(OperationalAttributeInfos.ENABLE);
schemaBuilder.defineObjectClass(ocBuilder.build());
schema = schemaBuilder.build();
}
return schema;
}
/**
* {@inheritDoc}
*/
public Object runScriptOnConnector(ScriptContext request, OperationOptions options) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
public Object runScriptOnResource(ScriptContext request, OperationOptions options) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
public FilterTranslator<String> createFilterTranslator(ObjectClass objectClass,
OperationOptions options) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
public void executeQuery(ObjectClass objectClass, String query, ResultsHandler handler,
OperationOptions options) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
public void sync(ObjectClass objectClass, SyncToken token, SyncResultsHandler handler,
final OperationOptions options) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
public SyncToken getLatestSyncToken(ObjectClass objectClass) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
public void test() {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
public Uid update(ObjectClass objectClass, Uid uid, Set<Attribute> replaceAttributes,
OperationOptions options) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
public Uid addAttributeValues(ObjectClass objectClass, Uid uid, Set<Attribute> valuesToAdd,
OperationOptions options) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
public Uid removeAttributeValues(ObjectClass objectClass, Uid uid,
Set<Attribute> valuesToRemove, OperationOptions options) {
throw new UnsupportedOperationException();
}
protected void fetchPasswordLevel() throws ConnectorException {
try {
SystemValue systemValue = new SystemValue(as400, "QPWDLVL");
Object qpwdlvl = systemValue.getValue();
if (qpwdlvl instanceof Integer) {
this.passwordLevel = ((Integer) qpwdlvl).intValue();
}
} catch (RequestNotSupportedException e) {
this.passwordLevel = QPWDLVL_UNSET;
LOG.error("QPWDLVL System Value not supported on this resource");
} catch (Exception e) {
throw new ConnectorException(e);
}
}
protected boolean runCommand(String command) throws ConnectorException {
boolean success = false;
try {
CommandCall cc = new CommandCall(as400);
cc.setCommand(command);
success = cc.run();
AS400Message[] msgs = cc.getMessageList();
if (success) {
// TODO implement
} else {
// TODO implement
}
} catch (Exception e) {
throw new ConnectorException(e);
}
return success;
}
}