ca.sqlpower.matchmaker.enterprise.MatchMakerClientSideSession.java Source code

Java tutorial

Introduction

Here is the source code for ca.sqlpower.matchmaker.enterprise.MatchMakerClientSideSession.java

Source

/*
 * Copyright (c) 2010, SQL Power Group Inc.
 *
 * This file is part of Power*MatchMaker.
 *
 * Power*MatchMaker is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Power*MatchMaker is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 */

package ca.sqlpower.matchmaker.enterprise;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.prefs.Preferences;

import org.apache.commons.codec.binary.Hex;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.olap4j.metadata.Datatype;
import org.springframework.security.AccessDeniedException;

import ca.sqlpower.architect.ddl.DDLGenerator;
import ca.sqlpower.dao.SPPersistenceException;
import ca.sqlpower.dao.SPPersisterListener;
import ca.sqlpower.dao.json.SPJSONMessageDecoder;
import ca.sqlpower.dao.json.SPJSONPersister;
import ca.sqlpower.dao.session.SessionPersisterSuperConverter;
import ca.sqlpower.dao.upgrade.UpgradePersisterManager;
import ca.sqlpower.diff.DiffChunk;
import ca.sqlpower.diff.DiffInfo;
import ca.sqlpower.diff.SimpleDiffChunkJSONConverter;
import ca.sqlpower.enterprise.AbstractNetworkConflictResolver;
import ca.sqlpower.enterprise.ClientSideSessionUtils;
import ca.sqlpower.enterprise.DataSourceCollectionUpdater;
import ca.sqlpower.enterprise.JSONMessage;
import ca.sqlpower.enterprise.JSONResponseHandler;
import ca.sqlpower.enterprise.ServerInfoProvider;
import ca.sqlpower.enterprise.TransactionInformation;
import ca.sqlpower.enterprise.client.ProjectLocation;
import ca.sqlpower.enterprise.client.SPServerInfo;
import ca.sqlpower.enterprise.client.User;
import ca.sqlpower.matchmaker.FolderParent;
import ca.sqlpower.matchmaker.MMRootNode;
import ca.sqlpower.matchmaker.MatchMakerSession;
import ca.sqlpower.matchmaker.MatchMakerSessionContext;
import ca.sqlpower.matchmaker.PlFolder;
import ca.sqlpower.matchmaker.Project;
import ca.sqlpower.matchmaker.TranslateGroupParent;
import ca.sqlpower.matchmaker.WarningListener;
import ca.sqlpower.object.AbstractPoolingSPListener;
import ca.sqlpower.object.SPObject;
import ca.sqlpower.sql.DataSourceCollection;
import ca.sqlpower.sql.JDBCDataSource;
import ca.sqlpower.sql.PlDotIni;
import ca.sqlpower.sql.SPDataSource;
import ca.sqlpower.sql.SpecificDataSourceCollection;
import ca.sqlpower.sqlobject.SQLDatabase;
import ca.sqlpower.sqlobject.SQLObjectException;
import ca.sqlpower.sqlobject.SQLTable;
import ca.sqlpower.sqlobject.UserDefinedSQLType;
import ca.sqlpower.swingui.event.SessionLifecycleEvent;
import ca.sqlpower.swingui.event.SessionLifecycleListener;
import ca.sqlpower.util.SQLPowerUtils;
import ca.sqlpower.util.UserPrompterFactory;
import ca.sqlpower.util.UserPrompter.UserPromptOptions;
import ca.sqlpower.util.UserPrompter.UserPromptResponse;
import ca.sqlpower.util.UserPrompterFactory.UserPromptType;

public class MatchMakerClientSideSession implements MatchMakerSession {

    private static Logger logger = Logger.getLogger(MatchMakerClientSideSession.class);

    private static CookieStore cookieStore = new BasicCookieStore();

    /**
     * The prefs node that will store information about the current settings of
     * the DDL generator and compare DM panels. Currently this is stored in prefs
     * because we want to store it per user for each project they are using. In the
     * future we may want to store this in the server, once per user per project.
     */
    private final Preferences prefs = Preferences.userNodeForPackage(MatchMakerClientSideSession.class);

    /**
     * Describes the location of the project that this session represents.
     */
    private final ProjectLocation projectLocation;

    /**
     * An {@link HttpClient} used to send updates to the server for changes to
     * the project and to receive updates from other users from the server.
     */
    private final HttpClient outboundHttpClient;

    /**
     * The persister that will update the project in this session with changes from
     * the server.
     */
    private final MatchMakerSessionPersister sessionPersister;

    /**
     * Holds the current ddlg
     */
    private DDLGenerator ddlGenerator;

    /**
     * Used to convert JSON sent from the server into persist calls to forward the
     * server changes to the {@link #sessionPersister}.
     */
    private final SPJSONPersister jsonPersister;
    private final MatchMakerNetworkConflictResolver updater;
    private final SPJSONMessageDecoder jsonMessageDecoder;
    private final DataSourceCollectionUpdater dataSourceCollectionUpdater;

    private AbstractPoolingSPListener deletionListener;

    private DataSourceCollection<JDBCDataSource> dataSourceCollection;

    /**
     * Used to store sessions which hold nothing but security info.
     */
    public static Map<String, MatchMakerClientSideSession> securitySessions = new HashMap<String, MatchMakerClientSideSession>();

    private final MatchMakerSession delegateSession;

    public static HttpClient createHttpClient(SPServerInfo serviceInfo) {
        return ClientSideSessionUtils.createHttpClient(serviceInfo, cookieStore);
    }

    /**
     * Map of server addresses to system workspaces. Use
     * {@link SPServerInfo#getServerAddress()} as the key.
     */
    public static Map<String, MatchMakerClientSideSession> getSecuritySessions() {
        return securitySessions;
    }

    /**
     * Exposes the shared cookie store so we don't spawn useless sessions
     * through the client.
     */
    public static CookieStore getCookieStore() {
        return cookieStore;
    }

    public static ProjectLocation createNewServerSession(SPServerInfo serviceInfo, String name,
            MatchMakerSession session)
            throws URISyntaxException, ClientProtocolException, IOException, JSONException {
        return ClientSideSessionUtils.createNewServerSession(serviceInfo, name, cookieStore,
                session.createUserPrompterFactory());
    }

    public static void deleteServerWorkspace(ProjectLocation projectLocation, MatchMakerSession session)
            throws URISyntaxException, ClientProtocolException, IOException {

        ClientSideSessionUtils.deleteServerWorkspace(projectLocation, cookieStore,
                session.createUserPrompterFactory());
    }

    public static void persistRevisionFromServer(ProjectLocation projectLocation, int revisionNo,
            SPJSONMessageDecoder decoder)
            throws IOException, URISyntaxException, SPPersistenceException, IllegalArgumentException {

        ClientSideSessionUtils.persistRevisionFromServer(projectLocation, revisionNo, decoder, cookieStore);
    }

    /**
     * This method reverts the server workspace specified by the given project location
     * to the specified revision number.
     * 
     * All sessions should automatically update to the reverted revision due to their Updater.
     * 
     * @returns The new global revision number, right after the reversion, or -1 if the server did not revert.
     * @throws IOException
     * @throws URISyntaxException
     * @throws JSONException 
     */
    public static int revertServerWorkspace(ProjectLocation projectLocation, int revisionNo)
            throws IOException, URISyntaxException, JSONException {
        return ClientSideSessionUtils.revertServerWorkspace(projectLocation, revisionNo, cookieStore);
    }

    public static ProjectLocation uploadProject(SPServerInfo serviceInfo, String name, File project,
            UserPrompterFactory session)
            throws URISyntaxException, ClientProtocolException, IOException, JSONException {
        return ClientSideSessionUtils.uploadProject(serviceInfo, name, project, session, cookieStore);
    }

    public MatchMakerClientSideSession(String name, ProjectLocation projectLocation,
            MatchMakerSession delegateSession) throws SQLObjectException {

        this.projectLocation = projectLocation;
        this.delegateSession = delegateSession;
        dataSourceCollectionUpdater = new MatchMakerDataSourceCollectionUpdater(projectLocation);

        String ddlgClass = prefs.get(this.projectLocation.getUUID() + ".ddlg", null);
        if (ddlgClass != null) {
            try {
                DDLGenerator ddlg = (DDLGenerator) Class
                        .forName(ddlgClass, true, MatchMakerClientSideSession.class.getClassLoader()).newInstance();
                setDDLGenerator(ddlg);
                ddlg.setTargetCatalog(prefs.get(this.projectLocation.getUUID() + ".targetCatalog", null));
                ddlg.setTargetSchema(prefs.get(this.projectLocation.getUUID() + ".targetSchema", null));
            } catch (Exception e) {
                delegateSession.createUserPrompterFactory()
                        .createUserPrompter("Cannot load DDL settings due to missing class " + ddlgClass,
                                UserPromptType.MESSAGE, UserPromptOptions.OK, UserPromptResponse.OK, null, "OK")
                        .promptUser("");
                logger.error("Cannot find DDL Generator for class " + ddlgClass
                        + ", ddl generator properties are not loaded.");
            }
        }

        outboundHttpClient = ClientSideSessionUtils.createHttpClient(projectLocation.getServiceInfo(), cookieStore);
        dataSourceCollection = getDataSources();

        sessionPersister = new MatchMakerSessionPersister("inbound-" + projectLocation.getUUID(), getWorkspace(),
                new MatchMakerPersisterSuperConverter(dataSourceCollection, getWorkspace()));
        sessionPersister.setWorkspaceContainer(this);

        jsonMessageDecoder = new SPJSONMessageDecoder(sessionPersister);

        updater = new MatchMakerNetworkConflictResolver(projectLocation, jsonMessageDecoder,
                ClientSideSessionUtils.createHttpClient(projectLocation.getServiceInfo(), cookieStore),
                outboundHttpClient, this);

        jsonPersister = new SPJSONPersister(updater);

        verifyServerLicense(projectLocation);
    }

    public boolean close() {
        if (getDDLGenerator() != null) {
            if (getDDLGenerator().getTargetCatalog() != null) {
                prefs.put(projectLocation.getUUID() + ".targetCatalog", getDDLGenerator().getTargetCatalog());
            }
            if (getDDLGenerator().getTargetSchema() != null) {
                prefs.put(projectLocation.getUUID() + ".targetSchema", getDDLGenerator().getTargetSchema());
            }
            prefs.put(projectLocation.getUUID() + ".ddlg", getDDLGenerator().getClass().getName());
        }

        try {
            //TODO: Figure out how to de-register the session &c.
        } catch (Exception e) {
            logger.error(e);

            delegateSession.createUserPrompterFactory()
                    .createUserPrompter("Cannot access the server to close the server session",
                            UserPromptType.MESSAGE, UserPromptOptions.OK, UserPromptResponse.OK,
                            UserPromptResponse.OK, "OK")
                    .promptUser("");
        }

        updater.interrupt();
        outboundHttpClient.getConnectionManager().shutdown();

        if (dataSourceCollection != null) {
            dataSourceCollectionUpdater.detach(dataSourceCollection);
        }

        getSystemWorkspace().removeSPListener(deletionListener);

        return delegateSession.close();
    }

    public void setDDLGenerator(DDLGenerator ddlGenerator) {
        this.ddlGenerator = ddlGenerator;

    }

    public DDLGenerator getDDLGenerator() {
        return ddlGenerator;
    }

    public MMRootNode getSystemWorkspace() {
        SPObject spo = getSecuritySessions().get(getProjectLocation().getServiceInfo().getServerAddress())
                .getWorkspace();
        if (!(spo instanceof MMRootNode)) {
            throw new RuntimeException("Your system workspace must be an MMRootNode, not a " + spo.getClass());
        }
        return (MMRootNode) spo;
    }

    public MatchMakerClientSideSession getSystemSession() {
        return getSecuritySessions().get(getProjectLocation().getServiceInfo().getServerAddress());
    }

    public ProjectLocation getProjectLocation() {
        return projectLocation;
    }

    public int getCurrentRevisionNumber() {
        return updater.getRevision();
    }

    public AbstractNetworkConflictResolver getUpdater() {
        return updater;
    }

    public User getUser() {
        String username = getProjectLocation().getServiceInfo().getUsername();
        User currentUser = null;
        for (User user : getSystemWorkspace().getChildren(User.class)) {
            if (user.getUsername().equals(username)) {
                currentUser = user;
            }
        }
        return currentUser;
    }

    /**
     * Retrieves a locally saved preference of type double.
     * @param prefName The name of the previously saved preference
     * @return The previously saved preference, or 0 if none exists yet
     */
    public double getPrefDouble(String prefName) {
        return getPrefDouble(prefName, 0);
    }

    /**
     * Retrieves a locally saved preference of type double.
     * @param prefName The name of the previously saved preference
     * @param def The value this function should return 
     * if no preference was previously saved
     */
    public double getPrefDouble(String prefName, double def) {
        return prefs.getDouble(projectLocation.getUUID() + "." + prefName, def);
    }

    /**
    * Enters a double value as a preference for this server session.
    * It will be able to be loaded by this local user in the future.
    */
    public void putPref(String prefName, double pref) {
        prefs.putDouble(projectLocation.getUUID() + "." + prefName, pref);
    }

    /**
     * Enters a String as a preference for this server session.
     * It will be able to be loaded by this local user in the future.
     */
    public void putPref(String prefName, String pref) {
        prefs.put(projectLocation.getUUID() + "." + prefName, pref);
    }

    /**
     * Retrieves a locally saved preference of type String.
     * @param prefName The name of the previously saved preference
     * @return The previously saved preference, or null if none exists yet
     */
    public String getPref(String prefName) {
        return getPref(prefName, null);
    }

    /**
     * Retrieves a locally saved preference of type String.
     * @param prefName The name of the previously saved preference
     * @param def The value this function should return 
     * if no preference was previously saved
     */
    public String getPref(String prefName, String def) {
        return prefs.get(projectLocation.getUUID() + "." + prefName, def);
    }

    public DataSourceCollection<JDBCDataSource> getDataSources() {
        if (dataSourceCollection == null) {
            dataSourceCollection = getDataSourcesFromServer();
            dataSourceCollectionUpdater.attach(dataSourceCollection);
        }
        return dataSourceCollection;
    }

    private DataSourceCollection<JDBCDataSource> getDataSourcesFromServer() {
        ResponseHandler<DataSourceCollection<JDBCDataSource>> plIniHandler = new ResponseHandler<DataSourceCollection<JDBCDataSource>>() {
            public DataSourceCollection<JDBCDataSource> handleResponse(HttpResponse response)
                    throws ClientProtocolException, IOException {

                if (response.getStatusLine().getStatusCode() == 401) {
                    throw new AccessDeniedException("Access Denied");
                }

                if (response.getStatusLine().getStatusCode() != 200) {
                    throw new IOException("Server error while reading data sources: " + response.getStatusLine());
                }

                PlDotIni plIni;
                try {
                    plIni = new PlDotIni(ClientSideSessionUtils.getServerURI(projectLocation.getServiceInfo(),
                            "/" + ClientSideSessionUtils.REST_TAG + "/jdbc/")) {

                        @Override
                        public List<UserDefinedSQLType> getSQLTypes() {
                            List<UserDefinedSQLType> types = new ArrayList<UserDefinedSQLType>();
                            types.addAll(delegateSession.getSQLTypes());
                            return types;
                        }

                        public SPDataSource getDataSource(String name) {
                            SPDataSource ds = super.getDataSource(name);
                            if (ds == null) {
                                mergeNewDataSources();
                                return super.getDataSource(name);
                            } else {
                                return ds;
                            }
                        }

                        public <C extends SPDataSource> C getDataSource(String name, java.lang.Class<C> classType) {
                            C ds = super.getDataSource(name, classType);
                            if (ds == null) {
                                mergeNewDataSources();
                                return super.getDataSource(name, classType);
                            } else {
                                return ds;
                            }
                        }

                        private void mergeNewDataSources() {
                            DataSourceCollection<JDBCDataSource> dsc = getDataSourcesFromServer();
                            for (SPDataSource merge : dsc.getConnections()) {
                                mergeDataSource(merge);
                            }
                        }
                    };
                    plIni.read(response.getEntity().getContent());
                    logger.debug("Data source collection has URI " + plIni.getServerBaseURI());
                } catch (URISyntaxException e) {
                    throw new RuntimeException(e);
                }

                return new SpecificDataSourceCollection<JDBCDataSource>(plIni, JDBCDataSource.class);
            }
        };

        DataSourceCollection<JDBCDataSource> dsc;
        try {
            dsc = ClientSideSessionUtils.executeServerRequest(outboundHttpClient, projectLocation.getServiceInfo(),
                    "/" + ClientSideSessionUtils.REST_TAG + "/data-sources/", plIniHandler);
        } catch (AccessDeniedException e) {
            throw e;
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }

        return dsc;
    }

    /**
      * Gets a list of DiffChunks representing the differences between the two revisions from the server.
      */
    public List<DiffChunk<DiffInfo>> getComparisonDiffChunks(int oldRevisionNo, int newRevisionNo)
            throws IOException, URISyntaxException, JSONException, SPPersistenceException {

        SPServerInfo serviceInfo = projectLocation.getServiceInfo();
        HttpClient httpClient = ClientSideSessionUtils.createHttpClient(serviceInfo, cookieStore);

        try {
            JSONMessage response = ClientSideSessionUtils.executeServerRequest(httpClient,
                    projectLocation.getServiceInfo(),
                    "/" + ClientSideSessionUtils.REST_TAG + "/project/" + projectLocation.getUUID() + "/compare",
                    "versions=" + oldRevisionNo + ":" + newRevisionNo, new JSONResponseHandler());

            return SimpleDiffChunkJSONConverter.decode(response.getBody());

        } finally {
            httpClient.getConnectionManager().shutdown();
        }

    }

    public List<TransactionInformation> getTransactionList(long fromVersion, long toVersion)
            throws IOException, URISyntaxException, JSONException, ParseException {

        SPServerInfo serviceInfo = projectLocation.getServiceInfo();
        HttpClient httpClient = ClientSideSessionUtils.createHttpClient(serviceInfo, cookieStore);

        try {

            logger.info("Getting transactions between " + fromVersion + " and " + toVersion);
            JSONMessage message = ClientSideSessionUtils.executeServerRequest(httpClient,
                    projectLocation.getServiceInfo(),
                    "/" + ClientSideSessionUtils.REST_TAG + "/project/" + projectLocation.getUUID()
                            + "/revision_list",
                    "versions=" + fromVersion + ":" + toVersion, new JSONResponseHandler());

            return ClientSideSessionUtils.decodeJSONRevisionList(message.getBody());

        } finally {
            httpClient.getConnectionManager().shutdown();
        }
    }

    public void persistProjectToServer() throws SPPersistenceException {
        final SPPersisterListener tempListener = new SPPersisterListener(jsonPersister,
                new MatchMakerPersisterSuperConverter(dataSourceCollection, getWorkspace()));
        tempListener.persistObject(getWorkspace(), 0);
    }

    public int revertServerWorkspace(int revisionNo) throws IOException, URISyntaxException, JSONException {
        return revertServerWorkspace(projectLocation, revisionNo);
    }

    public void startUpdaterThread() {

        final SPPersisterListener listener = new SPPersisterListener(jsonPersister, sessionPersister,
                new MatchMakerPersisterSuperConverter(dataSourceCollection, getWorkspace()));
        SQLPowerUtils.listenToHierarchy(getWorkspace(), listener);

        updater.setListener(listener);
        updater.setConverter(new SessionPersisterSuperConverter(dataSourceCollection, getWorkspace()));
        updater.start();

        delegateSession.addSessionLifecycleListener(new SessionLifecycleListener<MatchMakerSession>() {
            public void sessionClosing(SessionLifecycleEvent<MatchMakerSession> e) {
                SQLPowerUtils.unlistenToHierarchy(getWorkspace(), listener);
            }

            public void sessionOpening(SessionLifecycleEvent<MatchMakerSession> e) {
            }
        });
    }

    /**
     * This method can update any users password on the server given the correct
     * old password and done by a user with the privileges to change the user's
     * password.
     * 
     * @param session
     *            The client session that has the correct server information to
     *            post requests to the server.
     * @param username
     *            The user name of the user to update.
     * @param oldPassword
     *            The old password of the user to validate that the password can
     *            be updated correctly.
     * @param newPassword
     *            The new password to update to.
     * @param upf
     *            A user prompter to display message and error information to
     *            the user as necessary.
     */
    public void updateUserPassword(User user, String oldPassword, String newPassword, UserPrompterFactory upf) {
        SPServerInfo serviceInfo = getProjectLocation().getServiceInfo();

        HttpClient client = ClientSideSessionUtils.createHttpClient(serviceInfo, cookieStore);

        MessageDigest digester;
        try {
            digester = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException ex) {
            throw new RuntimeException(ex);
        }

        try {
            JSONObject begin = new JSONObject();
            begin.put("uuid", JSONObject.NULL);
            begin.put("method", "begin");

            JSONObject persist = new JSONObject();
            persist.put("uuid", user.getUUID());
            persist.put("propertyName", "password");
            persist.put("type", Datatype.STRING.toString());
            if (oldPassword == null) {
                persist.put("method", "persistProperty");
            } else {
                persist.put("method", "changeProperty");
                persist.put("oldValue", new String(Hex.encodeHex(digester.digest(oldPassword.getBytes()))));
            }
            persist.put("newValue", new String(Hex.encodeHex(digester.digest(newPassword.getBytes()))));

            JSONObject commit = new JSONObject();
            commit.put("uuid", JSONObject.NULL);
            commit.put("method", "commit");

            JSONArray transaction = new JSONArray();
            transaction.put(begin);
            transaction.put(persist);
            transaction.put(commit);

            URI serverURI = new URI("http", null, serviceInfo.getServerAddress(), serviceInfo.getPort(),
                    serviceInfo.getPath() + "/" + ClientSideSessionUtils.REST_TAG + "/project/system",
                    "currentRevision=" + getCurrentRevisionNumber(), null);
            HttpPost postRequest = new HttpPost(serverURI);
            postRequest.setEntity(new StringEntity(transaction.toString()));
            postRequest.setHeader("Content-Type", "application/json");
            HttpUriRequest request = postRequest;
            JSONMessage result = client.execute(request, new JSONResponseHandler());
            if (result.getStatusCode() != 200) {
                logger.warn("Failed password change");
                if (result.getStatusCode() == 412) {
                    upf.createUserPrompter("The password you have entered is incorrect.", UserPromptType.MESSAGE,
                            UserPromptOptions.OK, UserPromptResponse.OK, "OK", "OK").promptUser("");
                } else {
                    upf.createUserPrompter(
                            "Could not change the password due to the following: " + result.getBody()
                                    + " See logs for more details.",
                            UserPromptType.MESSAGE, UserPromptOptions.OK, UserPromptResponse.OK, "OK", "OK")
                            .promptUser("");
                }
            }
        } catch (AccessDeniedException ex) {
            logger.warn("Failed password change", ex);
            upf.createUserPrompter("The password you have entered is incorrect.", UserPromptType.MESSAGE,
                    UserPromptOptions.OK, UserPromptResponse.OK, "OK", "OK").promptUser("");
        } catch (Exception ex) {
            logger.warn("Failed password change", ex);
            upf.createUserPrompter(
                    "Could not change the password due to the following: " + ex.getMessage()
                            + " See logs for more details.",
                    UserPromptType.MESSAGE, UserPromptOptions.OK, UserPromptResponse.OK, "OK", "OK").promptUser("");
        }
    }

    protected void verifyServerLicense(ProjectLocation projectLocation) throws AssertionError {
        try {
            ServerInfoProvider.getServerVersion(projectLocation.getServiceInfo().getServerAddress(),
                    String.valueOf(projectLocation.getServiceInfo().getPort()),
                    projectLocation.getServiceInfo().getPath(), projectLocation.getServiceInfo().getUsername(),
                    projectLocation.getServiceInfo().getPassword(), cookieStore);
        } catch (Exception e) {
            throw new AssertionError("Exception encountered while verifying the server license:" + e.getMessage());
        }
    }

    @Override
    public void runInForeground(Runnable runner) {
        delegateSession.runInForeground(runner);

    }

    @Override
    public void runInBackground(Runnable runner) {
        delegateSession.runInBackground(runner);
    }

    @Override
    public boolean isForegroundThread() {
        return delegateSession.isForegroundThread();
    }

    @Override
    public SPObject getWorkspace() {
        return delegateSession.getWorkspace();
    }

    @Override
    public MatchMakerSessionContext getContext() {
        return delegateSession.getContext();
    }

    @Override
    public String getAppUser() {
        return delegateSession.getAppUser();
    }

    @Override
    public String getAppUserEmail() {
        return delegateSession.getAppUserEmail();
    }

    @Override
    public String getDBUser() {
        return delegateSession.getDBUser();
    }

    @Override
    public Date getSessionStartTime() {
        return delegateSession.getSessionStartTime();
    }

    @Override
    public UserPrompterFactory createUserPrompterFactory() {
        return delegateSession.createUserPrompterFactory();
    }

    @Override
    public PlFolder findFolder(String foldername) {
        return delegateSession.findFolder(foldername);
    }

    @Override
    public boolean isThisProjectNameAcceptable(String name) {
        return delegateSession.isThisProjectNameAcceptable(name);
    }

    @Override
    public long countProjectByName(String name) {
        return delegateSession.countProjectByName(name);
    }

    @Override
    public Project getProjectByName(String name) {
        return delegateSession.getProjectByName(name);
    }

    @Override
    public String createNewUniqueName() {
        return delegateSession.createNewUniqueName();
    }

    @Override
    public void handleWarning(String message) {
        delegateSession.handleWarning(message);
    }

    @Override
    public void addWarningListener(WarningListener l) {
        delegateSession.addWarningListener(l);
    }

    @Override
    public void removeWarningListener(WarningListener l) {
        delegateSession.removeWarningListener(l);
    }

    @Override
    public MMRootNode getRootNode() {
        return delegateSession.getRootNode();
    }

    @Override
    public TranslateGroupParent getTranslations() {
        return delegateSession.getTranslations();
    }

    @Override
    public FolderParent getBackupFolderParent() {
        return delegateSession.getBackupFolderParent();
    }

    @Override
    public FolderParent getCurrentFolderParent() {
        return delegateSession.getCurrentFolderParent();
    }

    @Override
    public SQLTable findPhysicalTableByName(String spDataSourceName, String catalog, String schema,
            String tableName) throws SQLObjectException {
        return delegateSession.findPhysicalTableByName(spDataSourceName, catalog, schema, tableName);
    }

    @Override
    public boolean tableExists(String spDataSourceName, String catalog, String schema, String tableName)
            throws SQLObjectException {
        return delegateSession.tableExists(spDataSourceName, catalog, schema, tableName);
    }

    @Override
    public boolean tableExists(SQLTable table) throws SQLObjectException {
        return delegateSession.tableExists(table);
    }

    @Override
    public boolean canSelectTable(SQLTable table) {
        return delegateSession.canSelectTable(table);
    }

    @Override
    public SQLDatabase getDatabase(JDBCDataSource dataSource) {
        return delegateSession.getDatabase(dataSource);
    }

    @Override
    public void addSessionLifecycleListener(SessionLifecycleListener<MatchMakerSession> listener) {
        delegateSession.addSessionLifecycleListener(listener);
    }

    @Override
    public void removeSessionLifecycleListener(SessionLifecycleListener<MatchMakerSession> listener) {
        delegateSession.removeSessionLifecycleListener(listener);

    }

    @Override
    public void addStatusMessage(String message) {
        delegateSession.addStatusMessage(message);
    }

    @Override
    public void removeStatusMessage() {
        delegateSession.removeStatusMessage();
    }

    @Override
    public List<UserDefinedSQLType> getSQLTypes() {
        return delegateSession.getSQLTypes();
    }

    @Override
    public UserDefinedSQLType getSQLType(int sqlType) {
        return delegateSession.getSQLType(sqlType);
    }

    @Override
    public UpgradePersisterManager getUpgradePersisterManager() {
        return delegateSession.getUpgradePersisterManager();
    }

    @Override
    public File getSavePoint() {
        logger.warn("Tried to get a savePoint on an enterprise session...");
        return null;
    }

    @Override
    public void setSavePoint(File savePoint) {
        delegateSession.setSavePoint(savePoint);
    }
}