/*****************************************************************************************
 * *** BEGIN LICENSE BLOCK *****
 *
 * Version: MPL 2.0
 *
 * echocat Jomon, Copyright (c) 2012-2014 echocat
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * *** END LICENSE BLOCK *****
 ****************************************************************************************/

package org.echocat.jomon.runtime.logging;

import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
import org.slf4j.Marker;
import org.slf4j.spi.LocationAwareLogger;

import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Handler;
import java.util.logging.LogManager;

import static java.util.logging.LogManager.getLogManager;
import static org.echocat.jomon.runtime.CollectionUtils.asImmutableList;
import static org.echocat.jomon.runtime.logging.LogLevel.*;
import static org.echocat.jomon.runtime.logging.LogLevels.allLogLevels;
import static org.echocat.jomon.runtime.util.ResourceUtils.closeQuietlyIfAutoCloseable;
import static org.slf4j.spi.LocationAwareLogger.*;

public class Slf4jUtils {

    private static final String FQCN = Slf4jUtils.class.getName();
    private static final Map<LogLevel, LogLevel> NORMALIZED_LEVEL_CACHE = new ConcurrentHashMap<>();

    public static void log(@Nonnull LocationAwareLogger logger, @Nonnull LogLevel level, @Nullable String fqcn, @Nullable Marker marker, @Nullable String message, @Nullable Object[] argArray, @Nullable Throwable t) {
        if (trace.equals(level)) {
            logger.log(marker, fqcn, TRACE_INT, message, argArray, t);
        } else if (debug.equals(level)) {
            logger.log(marker, fqcn, DEBUG_INT, message, argArray, t);
        } else if (info.equals(level)) {
            logger.log(marker, fqcn, INFO_INT, message, argArray, t);
        } else if (warning.equals(level)) {
            logger.log(marker, fqcn, WARN_INT, message, argArray, t);
        } else if (error.equals(level) || fatal.equals(level)) {
            logger.log(marker, fqcn, ERROR_INT, message, argArray, t);
        } else {
            log(logger, normalize(level), fqcn, marker, message, argArray, t);
        }
    }

    /**
     * Is the logger instance enabled for the given level?
     *
     * @return true if this Logger is enabled for the given level, false otherwise.
     */
    public static boolean isEnabled(@Nonnull Logger logger, @Nonnull LogLevel level) {
        final boolean result;
        if (trace.equals(level)) {
            result = logger.isTraceEnabled();
        } else if (debug.equals(level)) {
            result = logger.isDebugEnabled();
        } else if (info.equals(level)) {
            result = logger.isInfoEnabled();
        } else if (warning.equals(level)) {
            result = logger.isWarnEnabled();
        } else if (error.equals(level) || fatal.equals(level)) {
            result = logger.isErrorEnabled();
        } else {
            result = isEnabled(logger, normalize(level));
        }
        return result;
    }

    /**
     * Log a message at the given level.
     *
     * @param msg the message string to be logged
     */
    public static void log(@Nonnull Logger logger, @Nonnull LogLevel level, @Nullable String msg) {
        if (logger instanceof LocationAwareLogger) {
            log((LocationAwareLogger) logger, level, FQCN, null, msg, null, null);
        } else if (trace.equals(level)) {
            logger.trace(msg);
        } else if (debug.equals(level)) {
            logger.debug(msg);
        } else if (info.equals(level)) {
            logger.info(msg);
        } else if (warning.equals(level)) {
            logger.warn(msg);
        } else if (error.equals(level) || fatal.equals(level)) {
            logger.error(msg);
        } else {
            log(logger, normalize(level), msg);
        }
    }

    /**
     *
Log a message at the given level according to the specified format and argument.

     *
     *
This form avoids superfluous object creation when the logger is disabled for the given level.

     *
     * @param format the format string
     * @param arg the argument
     */
    public static void log(@Nonnull Logger logger, @Nonnull LogLevel level, @Nonnull String format, @Nullable Object arg) {
        if (logger instanceof LocationAwareLogger) {
            log((LocationAwareLogger) logger, level, FQCN, null, format, new Object[]{arg}, null);
        } else if (trace.equals(level)) {
            logger.trace(format, arg);
        } else if (debug.equals(level)) {
            logger.debug(format, arg);
        } else if (info.equals(level)) {
            logger.info(format, arg);
        } else if (warning.equals(level)) {
            logger.warn(format, arg);
        } else if (error.equals(level) || fatal.equals(level)) {
            logger.error(format, arg);
        } else {
            log(logger, normalize(level), format, arg);
        }
    }

    /**
     *
Log a message at the given level according to the specified format and arguments.

     *
     *
This form avoids superfluous object creation when the logger is disabled for the given level.

     *
     * @param format the format string
     * @param arg1 the first argument
     * @param arg2 the second argument
     */
    public static void log(@Nonnull Logger logger, @Nonnull LogLevel level, @Nonnull String format, @Nullable Object arg1, @Nullable Object arg2) {
        if (logger instanceof LocationAwareLogger) {
            log((LocationAwareLogger) logger, level, FQCN, null, format, new Object[]{arg1, arg2}, null);
        } else if (trace.equals(level)) {
            logger.trace(format, arg1, arg2);
        } else if (debug.equals(level)) {
            logger.debug(format, arg1, arg2);
        } else if (info.equals(level)) {
            logger.info(format, arg1, arg2);
        } else if (warning.equals(level)) {
            logger.warn(format, arg1, arg2);
        } else if (error.equals(level) || fatal.equals(level)) {
            logger.error(format, arg1, arg2);
        } else {
            log(logger, normalize(level), format, arg1, arg2);
        }
    }

    /**
     *
Log a message at the given level according to the specified format and arguments.

     *
     *
This form avoids superfluous object creation when the logger is disabled for the given level.

     *
     * @param format the format string
     * @param arguments a list of 3 or more arguments
     */
    public static void log(@Nonnull Logger logger, @Nonnull LogLevel level, @Nonnull String format, @Nullable Object... arguments) {
        if (logger instanceof LocationAwareLogger) {
            log((LocationAwareLogger) logger, level, FQCN, null, format, arguments, null);
        } else if (trace.equals(level)) {
            logger.trace(format, arguments);
        } else if (debug.equals(level)) {
            logger.debug(format, arguments);
        } else if (info.equals(level)) {
            logger.info(format, arguments);
        } else if (warning.equals(level)) {
            logger.warn(format, arguments);
        } else if (error.equals(level) || fatal.equals(level)) {
            logger.error(format, arguments);
        } else {
            log(logger, normalize(level), format, arguments);
        }
    }

    /**
     * Log an exception (throwable) at the given level with an accompanying message.
     *
     * @param msg the message accompanying the exception
     * @param t the exception (throwable) to log
     */
    public static void log(@Nonnull Logger logger, @Nonnull LogLevel level, @Nullable String msg, @Nullable Throwable t) {
        if (logger instanceof LocationAwareLogger) {
            log((LocationAwareLogger) logger, level, FQCN, null, msg, null, t);
        } else if (trace.equals(level)) {
            logger.trace(msg, t);
        } else if (debug.equals(level)) {
            logger.debug(msg, t);
        } else if (info.equals(level)) {
            logger.info(msg, t);
        } else if (warning.equals(level)) {
            logger.warn(msg, t);
        } else if (error.equals(level) || fatal.equals(level)) {
            logger.error(msg, t);
        } else {
            log(logger, normalize(level), msg, t);
        }
    }

    /**
     * Similar to {@link #isEnabled} method except that the marker data is also taken into account.
     *
     * @param marker The marker data to take into consideration
     * @return true if this Logger is enabled for the given level, false otherwise.
     */
    public static boolean isEnabled(@Nonnull Logger logger, @Nonnull LogLevel level, @Nonnull Marker marker) {
        final boolean result;
        if (trace.equals(level)) {
            result = logger.isTraceEnabled(marker);
        } else if (debug.equals(level)) {
            result = logger.isDebugEnabled(marker);
        } else if (info.equals(level)) {
            result = logger.isInfoEnabled(marker);
        } else if (warning.equals(level)) {
            result = logger.isWarnEnabled(marker);
        } else if (error.equals(level) || fatal.equals(level)) {
            result = logger.isErrorEnabled(marker);
        } else {
            result = isEnabled(logger, normalize(level), marker);
        }
        return result;
    }

    /**
     * Log a message with the specific Marker at the given level.
     *
     * @param marker the marker data specific to this log statement
     * @param msg the message string to be logged
     */
    public static void log(@Nonnull Logger logger, @Nonnull LogLevel level, @Nonnull Marker marker, @Nullable String msg) {
        if (logger instanceof LocationAwareLogger) {
            log((LocationAwareLogger) logger, level, FQCN, marker, msg, null, null);
        } else if (trace.equals(level)) {
            logger.trace(marker, msg);
        } else if (debug.equals(level)) {
            logger.debug(marker, msg);
        } else if (info.equals(level)) {
            logger.info(marker, msg);
        } else if (warning.equals(level)) {
            logger.warn(marker, msg);
        } else if (error.equals(level) || fatal.equals(level)) {
            logger.error(marker, msg);
        } else {
            log(logger, normalize(level), marker, msg);
        }
    }

    /**
     * This method is similar to {@link #log(Logger, LogLevel, String, Object)} method except that the marker data is also taken into consideration.
     *
     * @param marker the marker data specific to this log statement
     * @param format the format string
     * @param arg the argument
     */
    public static void log(@Nonnull Logger logger, @Nonnull LogLevel level, @Nonnull Marker marker, @Nonnull String format, @Nullable Object arg) {
        if (logger instanceof LocationAwareLogger) {
            log((LocationAwareLogger) logger, level, FQCN, marker, format, new Object[]{arg}, null);
        } else if (trace.equals(level)) {
            logger.trace(marker, format, arg);
        } else if (debug.equals(level)) {
            logger.debug(marker, format, arg);
        } else if (info.equals(level)) {
            logger.info(marker, format, arg);
        } else if (warning.equals(level)) {
            logger.warn(marker, format, arg);
        } else if (error.equals(level) || fatal.equals(level)) {
            logger.error(marker, format, arg);
        } else {
            log(logger, normalize(level), marker, format, arg);
        }
    }

    /**
     * This method is similar to {@link #log(Logger, LogLevel, String, Object, Object)} method except that the marker data is also taken into consideration.
     *
     * @param marker the marker data specific to this log statement
     * @param format the format string
     * @param arg1 the first argument
     * @param arg2 the second argument
     */
    public static void log(@Nonnull Logger logger, @Nonnull LogLevel level, @Nonnull Marker marker, @Nonnull String format, @Nullable Object arg1, @Nullable Object arg2) {
        if (logger instanceof LocationAwareLogger) {
            log((LocationAwareLogger) logger, level, FQCN, marker, format, new Object[]{arg1, arg2}, null);
        } else if (trace.equals(level)) {
            logger.trace(marker, format, arg1, arg2);
        } else if (debug.equals(level)) {
            logger.debug(marker, format, arg1, arg2);
        } else if (info.equals(level)) {
            logger.info(marker, format, arg1, arg2);
        } else if (warning.equals(level)) {
            logger.warn(marker, format, arg1, arg2);
        } else if (error.equals(level) || fatal.equals(level)) {
            logger.error(marker, format, arg1, arg2);
        } else {
            log(logger, normalize(level), marker, format, arg1, arg2);
        }
    }

    /**
     * This method is similar to {@link #log(Logger, LogLevel, String, Object...)} method except that the marker data is also taken into consideration.
     *
     * @param marker the marker data specific to this log statement
     * @param format the format string
     * @param arguments an array of arguments
     */
    public static void log(@Nonnull Logger logger, @Nonnull LogLevel level, @Nonnull Marker marker, @Nonnull String format, @Nullable Object... arguments) {
        if (logger instanceof LocationAwareLogger) {
            log((LocationAwareLogger) logger, level, FQCN, marker, format, arguments, null);
        } else if (trace.equals(level)) {
            logger.trace(marker, format, arguments);
        } else if (debug.equals(level)) {
            logger.debug(marker, format, arguments);
        } else if (info.equals(level)) {
            logger.info(marker, format, arguments);
        } else if (warning.equals(level)) {
            logger.warn(marker, format, arguments);
        } else if (error.equals(level) || fatal.equals(level)) {
            logger.error(marker, format, arguments);
        } else {
            log(logger, normalize(level), marker, format, arguments);
        }
    }

    /**
     * This method is similar to {@link #log(Logger, LogLevel, String, Throwable)} method except that the marker data is also taken into consideration.
     *
     * @param marker the marker data specific to this log statement
     * @param msg the message accompanying the exception
     * @param t the exception (throwable) to log
     */
    public static void log(@Nonnull Logger logger, @Nonnull LogLevel level, @Nonnull Marker marker, @Nullable String msg, @Nullable Throwable t) {
        if (logger instanceof LocationAwareLogger) {
            log((LocationAwareLogger) logger, level, FQCN, marker, msg, null, t);
        } else if (trace.equals(level)) {
            logger.trace(marker, msg, t);
        } else if (debug.equals(level)) {
            logger.debug(marker, msg, t);
        } else if (info.equals(level)) {
            logger.info(marker, msg, t);
        } else if (warning.equals(level)) {
            logger.warn(marker, msg, t);
        } else if (error.equals(level) || fatal.equals(level)) {
            logger.error(marker, msg, t);
        } else {
            log(logger, normalize(level), marker, msg, t);
        }
    }

    @Nonnull
    protected static LogLevel normalize(@Nonnull LogLevel level) {
        LogLevel result = NORMALIZED_LEVEL_CACHE.get(level);
        if (result == null) {
            result = debug;
            int lastDifference = differenceOf(debug, level);
            for (final LogLevel logLevel : allLogLevels()) {
                final int difference = differenceOf(logLevel, level);
                if (difference < lastDifference) {
                    result = logLevel;
                    lastDifference = difference;
                }
            }
            NORMALIZED_LEVEL_CACHE.put(level, result);
        }
        return result;
    }

    @Nonnegative
    protected static int differenceOf(@Nonnull LogLevel a, @Nonnull LogLevel b) {
        final int pa = a.getPriority();
        final int pb = b.getPriority();
        final int result;
        if (pa == pb) {
            result = 0;
        } else if (pa > pb) {
            result = pa - pb;
        } else {
            result = pb - pa;
        }
        return result;
    }

    private Slf4jUtils() {}

    @Nonnull
    public static Installation tryInstallSlf4jBridges(@Nullable ILoggerFactory loggerFactory) {
        return new CombinedInstallation(
            tryInstallClToSlf4jBridge(loggerFactory),
            tryInstallJulToSlf4jBridge(loggerFactory)
        );
    }

    @Nonnull
    public static Installation tryInstallClToSlf4jBridge(@Nullable ILoggerFactory loggerFactory) {
        Installation result = new NoopInstallation();
        try {
            final Class<?> type = Slf4jUtils.class.getClassLoader().loadClass("org.apache.commons.logging.LogFactory");
            final Field field = type.getDeclaredField("factories");
            field.setAccessible(true);
            if (Map.class.isAssignableFrom(field.getType())) {
                // noinspection unchecked
                final Map<ClassLoader, Object> factories = (Map<ClassLoader, Object>) field.get(null);
                if (factories != null) {
                    // noinspection SynchronizationOnLocalVariableOrMethodParameter
                    synchronized (factories) {
                        final ClassLoader classLoader = classLoader();
                        factories.put(classLoader, createClToSlf4jLoggerFactoryFor(loggerFactory));
                        result = new Cl2Slf4jInstallation(factories, classLoader);
                    }
                }
            }
        } catch (ClassNotFoundException | InstantiationException  | IllegalAccessException  |InvocationTargetException | NoSuchMethodException | NoSuchFieldException ignored) {}
        return result;
    }

    @Nonnull
    private static Object createClToSlf4jLoggerFactoryFor(@Nullable ILoggerFactory loggerFactory) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ClassNotFoundException {
        try {
            final Class<?> type = classLoader().loadClass("org.echocat.jomon.runtime.logging.Cl2Slf4jLoggerFactory");
            return type.getConstructor(ILoggerFactory.class).newInstance(loggerFactory);
        } catch (ClassNotFoundException | InstantiationException  | IllegalAccessException  |InvocationTargetException | NoSuchMethodException e) {
            // noinspection UseOfSystemOutOrSystemErr
            final PrintStream stream = System.err;
            stream.print("WARN Could not initiate instance of org.echocat.jomon.runtime.logging.Cl2Slf4jLoggerFactory.");
            e.printStackTrace(stream);
            throw e;
        }
    }

    @Nonnull
    protected static ClassLoader classLoader() {
        return Thread.currentThread().getContextClassLoader();
    }

    @Nonnull
    public static Installation tryInstallJulToSlf4jBridge() {
        return tryInstallJulToSlf4jBridge(null);
    }

    @Nonnull
    public static Installation tryInstallJulToSlf4jBridge(@Nullable ILoggerFactory loggerFactory) {
        return tryInstallJulToSlf4jBridge(loggerFactory, null);
    }

    @Nonnull
    public static Installation tryInstallJulToSlf4jBridge(@Nullable ILoggerFactory loggerFactory, @Nullable LogManager logManager) {
        final Jul2Slf4jHandler newHandler = new Jul2Slf4jHandler(loggerFactory);
        final LogManager manager = logManager != null ? logManager : getLogManager();
        manager.reset();
        final java.util.logging.Logger logger = manager.getLogger("");
        final List<Handler> originalHandlers = new ArrayList<>();
        for (final Handler oldHandlers : logger.getHandlers()) {
            logger.removeHandler(oldHandlers);
            originalHandlers.add(newHandler);
        }
        logger.addHandler(newHandler);
        return new Jul2Slf4jInstallation(originalHandlers, newHandler, manager);
    }

    public static void tryFixMdcInSlf4j() {
        try {
            final ClassLoader classLoader = Log4JUtils.class.getClassLoader();
            final Class<?> mdc = classLoader.loadClass("org.slf4j.MDC");
            final Class<?> mdcAdapter = classLoader.loadClass("org.slf4j.spi.MDCAdapter");
            final Field mdcAdapterField = mdc.getDeclaredField("mdcAdapter");
            if (mdcAdapterField.getType().equals(mdcAdapter)) {
                mdcAdapterField.setAccessible(true);
                final Object delegate = mdcAdapterField.get(null);
                final Object fixed = classLoader.loadClass("org.echocat.jomon.runtime.logging.FixingSlf4jMDCAdapter").getConstructor(mdcAdapter).newInstance(delegate);
                mdcAdapterField.set(null, fixed);
            }
        } catch (final Exception ignored) {}
    }

    public static interface Installation extends AutoCloseable {}

    private static class NoopInstallation implements Installation {

        @Override
        public void close() throws Exception {}

    }

    private static class CombinedInstallation implements Installation {

        @Nonnull
        private final Iterable<Installation> _installations;

        private CombinedInstallation(@Nullable Installation... installations) {
            this(asImmutableList(installations));
        }

        private CombinedInstallation(@Nonnull Iterable<Installation> installations) {
            _installations = installations;
        }

        @Override
        public void close() throws Exception {
            closeQuietlyIfAutoCloseable(_installations);
        }

    }

    private static class Cl2Slf4jInstallation implements Installation {

        @Nonnull
        private final Map<ClassLoader, Object> _factories;
        @Nonnull
        private final ClassLoader _classLoader;

        private Cl2Slf4jInstallation(@Nonnull Map<ClassLoader, Object> factories, @Nonnull ClassLoader classLoader) {
            _factories = factories;
            _classLoader = classLoader;
        }

        @Override
        public void close() throws Exception {
            synchronized (_factories) {
                _factories.remove(_classLoader);
            }
        }
    }

    private static class Jul2Slf4jInstallation implements Installation {

        @Nonnull
        private final Iterable<Handler> _originalHandlers;
        @Nonnull
        private final Handler _installedHandler;
        @Nonnull
        private final LogManager _logManager;

        private Jul2Slf4jInstallation(@Nonnull Iterable<Handler> originalHandlers, @Nonnull Handler installedHandler, @Nonnull LogManager logManager) {
            _originalHandlers = originalHandlers;
            _installedHandler = installedHandler;
            _logManager = logManager;
        }

        @Override
        public void close() throws Exception {
            final java.util.logging.Logger root = _logManager.getLogger("");
            _logManager.reset();
            root.removeHandler(_installedHandler);
            for (final Handler originalHandler : _originalHandlers) {
                root.addHandler(originalHandler);
            }
        }
    }

}


package org.eurekaclinical.scribeupext.provider;

/*
 * #%L
 * Eureka! Clinical ScribeUP Extensions
 * %%
 * Copyright (C) 2014 Emory University
 * %%
 * 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.
 * #L%
 */
import com.fasterxml.jackson.databind.JsonNode;
import org.eurekaclinical.scribeupext.profile.EurekaAttributesDefinition;
import org.eurekaclinical.scribeupext.profile.GoogleProfile;
import org.scribe.up.profile.JsonHelper;
import org.scribe.up.profile.UserProfile;
import org.scribe.up.profile.google2.Google2AttributesDefinition;

/**
 * Extracts the user's Google profile. This subclass of the original Google
 * OAuth2 provider fixes a bug where the scope is set incorrectly, and it
 * populates the profile attributes that Eureka! Clinical expects.
 *
 * @author Andrew Post
 */
public class Google2Provider extends org.scribe.up.provider.impl.Google2Provider {

    public Google2Provider() {
        setScope(this.scope);
    }

    /**
     * Returns the user's profile using the attributes that Eureka! Clinical
     * expects.
     *
     * @param body the JSON response from the user profile request.
     *
     * @return the user's profile.
     */
    @Override
    protected UserProfile extractUserProfile(final String body) {
        final GoogleProfile profile = new GoogleProfile();
        final JsonNode json = JsonHelper.getFirstNode(body);
        if (json != null) {
            profile.setId(JsonHelper.get(json, "id"));
            profile.addAttribute(EurekaAttributesDefinition.USERNAME, JsonHelper.get(json, Google2AttributesDefinition.EMAIL));
            profile.addAttribute(EurekaAttributesDefinition.FIRSTNAME, JsonHelper.get(json, Google2AttributesDefinition.GIVEN_NAME));
            profile.addAttribute(EurekaAttributesDefinition.LASTNAME, JsonHelper.get(json, Google2AttributesDefinition.FAMILY_NAME));
            profile.addAttribute(EurekaAttributesDefinition.FULLNAME, JsonHelper.get(json, Google2AttributesDefinition.NAME));
            profile.addAttribute(EurekaAttributesDefinition.EMAIL, JsonHelper.get(json, Google2AttributesDefinition.EMAIL));
        }
        return profile;
    }
}


package org.eurekaclinical.scribeupext.service;

/*
 * #%L
 * Eureka! Clinical ScribeUP Extensions
 * %%
 * Copyright (C) 2014 Emory University
 * %%
 * 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.
 * #L%
 *
 * 20160222 - Stephen Granite (sgranite@jhu.edu) - added redirect_uri parameter to authorization request
 * This was done to resolve a change in Globus Authenticaton that required the redirect to be in the
 * access token call as well
 */
import com.fasterxml.jackson.databind.JsonNode;
import org.eurekaclinical.scribeupext.GlobusApi;
import org.scribe.builder.api.DefaultApi20;
import org.scribe.model.OAuthConfig;
import org.scribe.model.OAuthRequest;
import org.scribe.model.ProxyOAuthRequest;
import org.scribe.model.Response;
import org.scribe.model.Token;
import org.scribe.model.Verifier;
import org.scribe.oauth.OAuth20ServiceImpl;
import org.scribe.up.profile.JsonHelper;

/**
 * Gets an access token for an authorized user.
 *
 * @author Andrew Post
 */
public class GlobusOAuth20ServiceImpl extends OAuth20ServiceImpl {

    protected final DefaultApi20 api;
    protected final OAuthConfig config;
    protected final String proxyHost;
    protected final int proxyPort;

    /**
     * Instantiates this class with an OAuth API instance, query parameters,
     * and a proxy host and port, if any.
     *
     * @param api the access token request URL to use.
     * @param config query parameters for requesting an access token.
     * @param proxyHost the proxy host, if any. Can be null.
     * @param proxyPort the proxy port. Ignored if there is not a proxy host.
     */
    public GlobusOAuth20ServiceImpl(GlobusApi api, OAuthConfig config,
            String proxyHost, int proxyPort) {
        super(api, config);
        this.api = api;
        this.config = config;
        this.proxyHost = proxyHost;
        this.proxyPort = proxyPort;
    }

    /**
     * Makes the call to request an access token for an authorized user.
     *
     * @param requestToken not used.
     * @param verifier the code query parameter that Globus included in the
     * redirect after the authorization call.
     *
     * @return the access token.
     */
    @Override
    public Token getAccessToken(Token requestToken, Verifier verifier) {
        OAuthRequest request
                = new ProxyOAuthRequest(this.api.getAccessTokenVerb(),
                        this.api.getAccessTokenEndpoint(), this.proxyHost, this.proxyPort);
        String userpass = this.config.getApiKey() + ":" + this.config.getApiSecret();
        String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(userpass.getBytes());
        request.addHeader("Authorization", basicAuth);
        request.addBodyParameter("grant_type", "authorization_code");
        request.addBodyParameter("code", verifier.getValue());
        request.addBodyParameter("redirect_uri", config.getCallback());
        Response response = request.send();
        String body = response.getBody();
        JsonNode json = JsonHelper.getFirstNode(body);
        if (json != null) {
            return new Token((String) JsonHelper.get(json, "access_token"), "", body);
        } else {
            return null;
        }

    }

    /**
     * Adds an authorization header containing the bearer token to a request.
     * It is intended for use in API calls after getting the access token, such
     * as requesting the user's profile.
     *
     * @param accessToken the user's access token.
     * @param request the requests.
     */
    @Override
    public void signRequest(Token accessToken, OAuthRequest request) {
        request.addHeader("Authorization", "Bearer " + accessToken.getToken());
    }
}


package org.eurekaclinical.scribeupext.provider;

/*
 * #%L
 * Eureka! Clinical ScribeUP Extensions
 * %%
 * Copyright (C) 2014 Emory University
 * %%
 * 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.
 * #L%
 */
import com.fasterxml.jackson.databind.JsonNode;
import org.eurekaclinical.scribeupext.GlobusApi;
import org.eurekaclinical.scribeupext.profile.EurekaAttributesDefinition;
import org.eurekaclinical.scribeupext.profile.GlobusAttributesDefinition;
import org.eurekaclinical.scribeupext.profile.GlobusProfile;
import org.eurekaclinical.scribeupext.service.GlobusOAuth20ServiceImpl;
import java.util.concurrent.TimeUnit;
import org.scribe.model.OAuthConfig;
import org.scribe.model.ProxyOAuthRequest;
import org.scribe.model.Response;
import org.scribe.model.SignatureType;
import org.scribe.model.Token;
import org.scribe.model.Verb;
import org.scribe.up.profile.JsonHelper;
import org.scribe.up.profile.UserProfile;
import org.scribe.up.provider.BaseOAuth20Provider;
import org.scribe.up.provider.exception.HttpException;

/**
 * Extracts the user's Globus profile.
 *
 * Globus changed their usernames in August, 2017 by appending
 * @globusid.org to them. This is true even for user accounts that
 * predate the change. To give some time for users of this library to move to
 * the new username scheme, we provide a system property,
 * scribeupext.globus.legacyUsernames, which if true,
 * will cause this class to remove the @globusid.org suffix from
 * usernames when extracting a user's profile. This system property may be
 * removed in the next major release.
 *
 * @author Andrew Post
 */
public class GlobusProvider extends BaseOAuth20Provider {

    private static final boolean LEGACY_USERNAMES = Boolean.getBoolean("scribeupext.globus.legacyUsernames");

    @Override
    protected GlobusProvider newProvider() {
        return new GlobusProvider();
    }

    /**
     * Initializes the signing of Globus API calls with an access token. A
     * superclass that overrides this method must call this method in the
     * overridden version, or you must override {@link #sendRequestForData(org.scribe.model.Token, java.lang.String) }
     * with a new implementation.
     */
    @Override
    protected void internalInit() {
        this.service = new GlobusOAuth20ServiceImpl(new GlobusApi(),
                new OAuthConfig(this.key, this.secret, this.callbackUrl,
                        SignatureType.Header, "user", null), this.proxyHost,
                this.proxyPort);
    }

    /**
     * Returns the current URL for requesting the user's profile.
     *
     * @return the URL for requesting the user's profile.
     */
    @Override
    protected String getProfileUrl() {
        return "https://auth.globus.org/v2/oauth2/userinfo";
    }

    /**
     * Calls any Globus endpoint that requires already being authenticated.
     * Relies on {@link #internalInit() } to setup request signing.
     *
     * @param accessToken the access token to use when signing the request.
     * @param dataUrl the endpoint to call.
     * @return the response body.
     *
     * @throws HttpException if an error occurred calling the endpoint.
     */
    @Override
    protected String sendRequestForData(Token accessToken, String dataUrl) throws HttpException {
        final ProxyOAuthRequest request = new ProxyOAuthRequest(Verb.GET, dataUrl, this.proxyHost, this.proxyPort);
        if (this.connectTimeout != 0) {
            request.setConnectTimeout(this.connectTimeout, TimeUnit.MILLISECONDS);
        }
        if (this.readTimeout != 0) {
            request.setReadTimeout(this.readTimeout, TimeUnit.MILLISECONDS);
        }
        this.service.signRequest(accessToken, request);
        request.addHeader("Content-Type", "application/json");
        final Response response = request.send();
        final int code = response.getCode();
        final String body = response.getBody();
        if (code != 200) {
            throw new HttpException(code, body);
        }
        return body;
    }

    /**
     * Returns the user's profile using the attributes that Eureka! Clinical
     * expects. If the system property
     * scribeupext.globus.legacyUsernames is set and has value
     * true (case-insensitive), this method will omit the
     * @globusid.org suffix when extracting the user's username.
     *
     * @param body the JSON response from the user profile request.
     *
     * @return the user's profile.
     */
    @Override
    protected UserProfile extractUserProfile(final String body) {
        GlobusProfile profile = new GlobusProfile();
        JsonNode json = JsonHelper.getFirstNode(body);
        if (json != null) {
            String username = JsonHelper.get(json, GlobusAttributesDefinition.USERNAME).toString();
            if (LEGACY_USERNAMES) {
                username = username.split("@")[0];
            }
            profile.setId(username);
            profile.addAttribute(EurekaAttributesDefinition.USERNAME, username);
            profile.addAttribute(EurekaAttributesDefinition.FULLNAME, JsonHelper.get(json, GlobusAttributesDefinition.FULLNAME));
            profile.addAttribute(EurekaAttributesDefinition.EMAIL, JsonHelper.get(json, GlobusAttributesDefinition.EMAIL));
        }
        return profile;
    }
}


package org.eurekaclinical.scribeupext.provider;

/*
 * #%L
 * Eureka! Clinical ScribeUP Extensions
 * %%
 * Copyright (C) 2014 Emory University
 * %%
 * 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.
 * #L%
 */
import com.fasterxml.jackson.databind.JsonNode;
import org.eurekaclinical.scribeupext.profile.EurekaAttributesDefinition;
import org.eurekaclinical.scribeupext.profile.GitHubProfile;
import org.scribe.up.profile.JsonHelper;
import org.scribe.up.profile.UserProfile;
import org.scribe.up.profile.github.GitHubAttributesDefinition;

/**
 * Extracts the user's GitHub profile. This subclass of the original GitHub
 * OAuth provider populates the profile attributes that Eureka! Clinical
 * expects.
 *
 * @author Andrew Post
 */
public class GitHubProvider extends org.scribe.up.provider.impl.GitHubProvider {

    /**
     * Returns the user's profile using the attributes that Eureka! Clinical
     * expects.
     *
     * @param body the JSON response from the user profile request.
     *
     * @return the user's profile.
     */
    @Override
    protected UserProfile extractUserProfile(String body) {
        final GitHubProfile profile = new GitHubProfile();
        final JsonNode json = JsonHelper.getFirstNode(body);
        if (json != null) {
            profile.setId(JsonHelper.get(json, "id"));
            profile.addAttribute(EurekaAttributesDefinition.USERNAME, JsonHelper.get(json, GitHubAttributesDefinition.LOGIN));
            profile.addAttribute(EurekaAttributesDefinition.FULLNAME, JsonHelper.get(json, GitHubAttributesDefinition.NAME));
            profile.addAttribute(EurekaAttributesDefinition.EMAIL, JsonHelper.get(json, GitHubAttributesDefinition.EMAIL));
            profile.addAttribute(EurekaAttributesDefinition.ORGANIZATION, JsonHelper.get(json, GitHubAttributesDefinition.COMPANY));
        }
        return profile;
    }

}


package org.eurekaclinical.scribeupext.provider;

/*
 * #%L
 * Eureka! Clinical ScribeUP Extensions
 * %%
 * Copyright (C) 2014 Emory University
 * %%
 * 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.
 * #L%
 */
import com.fasterxml.jackson.databind.JsonNode;
import org.eurekaclinical.scribeupext.profile.EurekaAttributesDefinition;
import org.eurekaclinical.scribeupext.profile.TwitterProfile;
import org.scribe.up.profile.JsonHelper;
import org.scribe.up.profile.UserProfile;
import org.scribe.up.profile.twitter.TwitterAttributesDefinition;

/**
 * Extracts the user's Twitter profile. This subclass of the original Google
 * OAuth2 provider overrides the URL for getting the user's profile with the
 * current URL, and it populates the profile attributes that Eureka! Clinical
 * expects.
 *
 * @author Andrew Post
 */
public class SSLTwitterProvider extends org.scribe.up.provider.impl.TwitterProvider {

    /**
     * Returns the current URL for requesting the user's profile.
     *
     * @return the URL for requesting the user's profile.
     */
    @Override
    protected String getProfileUrl() {
        return "https://api.twitter.com/1.1/account/verify_credentials.json";
    }

    /**
     * Returns the user's profile using the attributes that Eureka! Clinical
     * expects.
     *
     * @param body the JSON response from the user profile request.
     *
     * @return the user's profile.
     */
    @Override
    protected UserProfile extractUserProfile(final String body) {
        final TwitterProfile profile = new TwitterProfile();
        final JsonNode json = JsonHelper.getFirstNode(body);
        if (json != null) {
            profile.setId(JsonHelper.get(json, "id"));
            profile.addAttribute(EurekaAttributesDefinition.USERNAME, JsonHelper.get(json, TwitterAttributesDefinition.SCREEN_NAME));
            profile.addAttribute(EurekaAttributesDefinition.FULLNAME, JsonHelper.get(json, TwitterAttributesDefinition.NAME));
        }
        return profile;
    }

}


package org.eurekaclinical.scribeupext;

/*
 * #%L
 * Eureka! Clinical ScribeUP Extensions
 * %%
 * Copyright (C) 2014 Emory University
 * %%
 * 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.
 * #L%
 */
import org.scribe.builder.api.DefaultApi20;
import org.scribe.extractors.AccessTokenExtractor;
import org.scribe.extractors.JsonTokenExtractor;
import org.scribe.model.OAuthConfig;
import org.scribe.model.Verb;
import org.scribe.utils.OAuthEncoder;
import org.scribe.utils.Preconditions;

/**
 * The Globus API for authorizing the user and getting an access token.
 *
 * @author Andrew Post
 */
public class GlobusApi extends DefaultApi20 {

    private static final String AUTHORIZE_URL = "https://auth.globus.org/v2/oauth2/authorize?response_type=code&client_id=%s&redirect_uri=%s&scope=%s";

    /**
     * Space-delimited set of scopes.
     */
    private static final String SCOPES = "openid email profile";

    /**
     * Returns the URL for requesting an access token.
     *
     * @return the URL for requesting an access token.
     */
    @Override
    public String getAccessTokenEndpoint() {
        return "https://auth.globus.org/v2/oauth2/token";
    }

    /**
     * Returns the verb to use for requesting an access token.
     *
     * @return the verb to use for requesting an access token.
     */
    @Override
    public Verb getAccessTokenVerb() {
        return Verb.POST;
    }

    /**
     * Returns an object for parsing a successful response from the
     * authorization call and extracting the access token.
     *
     * @return an object that can extract the access token from Globus'
     * response.
     */
    @Override
    public AccessTokenExtractor getAccessTokenExtractor() {
        return new JsonTokenExtractor();
    }

    /**
     * Returns the URL for authorizing the user.
     *
     * @param config query parameters to add to the base URL.
     *
     * @return the URL for authorizing the user.
     */
    @Override
    public String getAuthorizationUrl(OAuthConfig config) {
        Preconditions.checkValidUrl(config.getCallback(),
                "Must provide a valid url as callback.");
        return String.format(AUTHORIZE_URL, config.getApiKey(),
                OAuthEncoder.encode(config.getCallback()), SCOPES);
    }
}


package org.criteria4jpa.projection;

import java.math.BigDecimal;
import java.math.BigInteger;

import org.criteria4jpa.Criteria;
import org.criteria4jpa.CriteriaUtils;

/**
 *
 *

 * Factory class for {@link Projection} instances that can be added
 * to a criteria by calling {@link Criteria#setProjection(Projection)}.
 *

 *
 * @author Christian Kaltepoth
 *
 */
public class Projections {

  /**
   * Creates a "distinct" projection wrapping another projection.
   *
   * @param projection the projection to wrap with a "distinct"
   * @return a new projection instance
   */
  public static Projection distinct(Projection projection) {
    return new DistinctProjection(projection);
  }

  /**
   * Creates a projection list projection that wraps a list
   * if other projections. You may add projections to the list by
   * calling {@link ProjectionList#add(Projection)} on the
   * returned projection. If you use a projection list for your
   * criteria, that query will return an object array.
   *
   * @return new instance of {@link ProjectionList}
   */
  public static ProjectionList projectionList() {
    return new ProjectionList();
  }

  /**
   * This method only exists for compatibility with the
   * Hibernate Criteria API and simply delegates the call
   * to {@link #relativePath(String)}.
   *
   * @param relativePath relative path expression of a field
   * @return new projection instance
   */
  public static Projection property(String relativePath) {
    return relativePath(relativePath);
  }

  /**
   * This method only exists for compatibility with the
   * Hibernate Criteria API and simply delegates the call
   * to {@link #relativeGroupPath(String)}.
   *
   * @param relativePath relative path expression of a field
   * @return new projection instance
   * @since 0.3
   *
   */
  public static Projection groupProperty(String relativePath) {
    return relativeGroupPath(relativePath);
  }

  /**
   *

   * This projection can be used if you want the criteria to
   * return a certain persistent field or a
   * single-valued relationship field.
   *

   *
   *

   * Please note that the path expression must be relative to
   * the criteria this projection is added to.
   *

   *
   * @param path relative path expression
   * @return new projection instance
   */
  public static Projection relativePath(String path) {
    return new PathProjection(path, false, false);
  }

  /**
   *

   * This projection can be used if you want the criteria to
   * return a certain persistent field or a
   * single-valued relationship field.
   *

   *
   *

   * This projects creates a grouping by adding the field
   * to the GROUP BY clause of the query.
   *

   *
   *

   * Please note that the path expression must be relative to
   * the criteria this projection is added to.
   *

   *
   * @param path relative path expression
   * @return new projection instance
   * @since 0.3
   */
  public static Projection relativeGroupPath(String path) {
    return new PathProjection(path, false, true);
  }

  /**
   *

   * This projection can be used if you want the criteria to
   * return a certain persistent field or a
   * single-valued relationship field.
   *

   *
   *

   * This projects creates a grouping by adding the field
   * to the GROUP BY clause of the query.
   *

   *
   *

   * Please note that the path expression must be absolute
   * meaning that it has to start with an alias created.
   *

   *
   * @see CriteriaUtils#createCriteria(javax.persistence.EntityManager, Class, String)
   * @see Criteria#createCriteria(String, String)
   *
   * @param path absolute path expression
   * @return new projection instance
   */
  public static Projection absolutePath(String path) {
    return new PathProjection(path, false, false);
  }

  /**
   *

   * This projection can be used if you want the criteria to
   * return a certain persistent field or a
   * single-valued relationship field.
   *

   *
   *

   * Please note that the path expression must be absolute
   * meaning that it has to start with an alias created.
   *

   *
   * @see CriteriaUtils#createCriteria(javax.persistence.EntityManager, Class, String)
   * @see Criteria#createCriteria(String, String)
   *
   * @param path absolute path expression
   * @return new projection instance
   * @since 0.3
   */
  public static Projection absoluteGroupPath(String path) {
    return new PathProjection(path, false, true);
  }

  /**
   * Creates a projection referring to the root entity of the
   * criteria hierarchy it is added to.
   *
   * @return new projection instance
   */
  public static Projection rootEntity() {
    return new RootEntityProjection();
  }

  /**
   *

   * Returns a projection referring to the distinct root entities of
   * the criteria hierarchy it is added to.
   *

   *
   *

   * You can get the same result by calling a combination of
   * {@link #distinct(Projection)} and {@link #rootEntity()}.
   *

   *
   * @return new projection instance
   */
  public static Projection distinctRootEntity() {
    return new DistinctProjection( new RootEntityProjection() );
  }

  /**
   * A projection that returns the smallest value of a
   * persistent field. The result of the query will have the
   * same type as the specified field.
   *
   * @param relativePath relative path of a persistent field
   * @return new projection instance
   */
  public static Projection min(String relativePath) {
    return new FunctionProjection("MIN", new PathProjection(relativePath, false, false));
  }

  /**
   * A projection that returns the largest value of a
   * persistent field. The result of the query will have the
   * same type as the specified field.
   *
   * @param relativePath relative path of a persistent field
   * @return new projection instance
   */
  public static Projection max(String relativePath) {
    return new FunctionProjection("MAX", new PathProjection(relativePath, false, false));
  }

  /**
   * A projection that returns the sum of all values.
   * The result of the query will be a {@link Long} (for integral fields),
   * {@link Double} (for floating point fields),
   * {@link BigInteger} (for BigInteger fields) or
   * {@link BigDecimal} (for BigDecimal fields)
   *
   * @param relativePath relative path of a persistent field
   * @return new projection instance
   */
  public static Projection sum(String relativePath) {
    return new FunctionProjection("SUM", new PathProjection(relativePath, false, false));
  }

  /**
   * A projection that returns the average of all values.
   * The result of the query will always be a {@link Double}.
   *
   * @param relativePath relative path of a persistent field
   * @return new projection instance
   */
  public static Projection avg(String relativePath) {
    return new FunctionProjection("AVG", new PathProjection(relativePath, false, false));
  }

  /**
   * Creates a count projection for the specified relative path.
   * In most cases you can may use {@link #count(String)}
   * or {@link #countDistinct(String)} instead of this method.
   * The result of the query will always be a {@link Long}.
   *
   * @param projection nested projection
   * @return new projection instance
   */
  public static CountProjection count(Projection projection) {
    return new CountProjection(projection);
  }

  /**
   *

   * Creates a count projection for the specified relative path.
   *

   *
   *

   * Calling the method is the same as manually chaining calls to {@link #count(Projection)}
   * and {@link #relativePath(String)}.
   *

   *
   *

   * The result of the query will always be a {@link Long}.
   *

   *
   * @param relativePath relative path
   * @return new projection instance
   */
  public static CountProjection count(String relativePath) {
    return new CountProjection(
        new PathProjection(relativePath, false, false)
    );
  }

  /**
   *

   * Creates a "constructor expression" projection for the specified type.
   *

   *
   *

   * The caller must add child projections to this projection by calling
   * {@link ConstructorProjection#add(Projection)}. The child projections must
   * match a constructor of the type supplied during creation of the
   * projection.
   *

   *
   * @param type
   *          The class to use for the constructor expression.
   * @return new projection instance
   * @since 0.3
   */
  public static ConstructorProjection constructor(Class<?> type) {
    return new ConstructorProjection(type);
  }

  /**
   *

   * Creates a "count distinct" projection for the specified relative path.
   *

   *
   *

   * Calling the method is the same as manually chaining calls to {@link #count(Projection)},
   * {@link #distinct(Projection)} and {@link #relativePath(String)}.
   *

   *
   *

   * The result of the query will always be a {@link Long}.
   *

   *
   * @param relativePath relative path
   * @return new projection instance
   */
  public static CountProjection countDistinct(String relativePath) {
    return new CountProjection(
        new DistinctProjection(
            new PathProjection(relativePath, false, false)
        )
    );
  }

  /**
   *

   * Creates a count projection for the root entity of the criteria.
   *

   *
   *

   * You will get the number of root entities matching the criteria as a result.
   * Please note that you should use {@link #rowCountDistinct()} to get the
   * expected result the criteria creates joins on collection-valued relationship fields.
   *

   *
   *

   * Calling the method is the same as manually chaining calls to {@link #count(Projection)}
   * and {@link #rootEntity()}.
   *

   *
   *

   * The result of the query will always be a {@link Long}.
   *

   *
   * @return new projection instance
   */
  public static Projection rowCount() {
    return new CountProjection(
        new RootEntityProjection()
    );
  }

  /**
   *

   * Creates a "count distinct" projection for the root entity of the criteria.
   *

   *
   *

   * You will get the number of root entities matching the criteria as a result.
   * It is recommended to use this method instead of {@link #rowCount()},
   * when the criteria creates joins on collection-valued relationship fields.
   *

   *
   *

   * Calling the method is the same as manually chaining calls to {@link #count(Projection)},
   * {@link #distinct(Projection)} and {@link #rootEntity()}.
   *

   *
   *

   * The result of the query will always be a {@link Long}.
   *

   *
   * @return new projection instance
   */
  public static Projection rowCountDistinct() {
    return new CountProjection(
        new DistinctProjection(
            new RootEntityProjection()
        )
    );
  }

}


/*******************************************************************************
 * <copyright>
 *
 * Copyright (c) 2014 Eteration A.S.
 * All rights reserved.
 * 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.
 *
 *
 *     Derivative Works
 *     Parts of this program are derived from content from Eclipse Foundation
 *     that are made available under the terms of the Eclipse Public License v1.0.
 *      http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Naci Dai, Eteration A.S. - initial API, implementation and documentation
 *
 * </copyright>
 *
 *******************************************************************************/
package org.glassmaker.ui.editor.wizards;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Properties;

import org.apache.maven.archetype.catalog.Archetype;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.IPageChangingListener;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.PageChangingEvent;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.m2e.core.MavenPlugin;
import org.eclipse.m2e.core.project.ProjectImportConfiguration;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWizard;
import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;

/**
 * This is a simple new wizard. Its role is to create a new project.
 */

public class ProjectWizard extends Wizard implements INewWizard {
	private WizardNewProjectCreationPage projectPage;
	private ProjectWizardParametersPage parametersPage;
	private ISelection selection;
	protected ProjectImportConfiguration importConfiguration = new ProjectImportConfiguration();

	/**
	 * Constructor for ProjectWizard.
	 */
	public ProjectWizard() {
		super();
		setNeedsProgressMonitor(true);
	}

	/**
	 * Adding the page to the wizard.
	 */

	public void addPages() {
		projectPage = new WizardNewProjectCreationPage("Glassmaker Project");
		parametersPage = new ProjectWizardParametersPage();
		addPage(projectPage);
		addPage(parametersPage);
	}

	@Override
	public IWizardPage getNextPage(IWizardPage page) {
		if(page == projectPage)
			parametersPage.setProjectName(getProjectName());
		return super.getNextPage(page);
	}
	/**
	 * This method is called when 'Finish' button is pressed in the wizard. We
	 * will create an operation and run it using wizard as execution context.
	 */
	public boolean performFinish() {
		final String containerName = getProjectName();
		final IPath location = projectPage.useDefaults() ? null : projectPage.getLocationPath();

		IRunnableWithProgress op = new IRunnableWithProgress() {
			public void run(IProgressMonitor monitor) throws InvocationTargetException {
				try {
					doFinish(containerName, location, monitor);
				} catch (CoreException e) {
					throw new InvocationTargetException(e);
				} finally {
					monitor.done();
				}
			}
		};
		try {
			getContainer().run(true, false, op);
		} catch (InterruptedException e) {
			return false;
		} catch (InvocationTargetException e) {
			Throwable realException = e.getTargetException();
			MessageDialog.openError(getShell(), "Error", realException.getMessage());
			return false;
		}
		return true;
	}

	public String getProjectName() {
		return projectPage.getProjectName();
	}

	/**
	 * The worker method. It will find the container, create the file if missing
	 * or just replace its contents, and open the editor on the newly created
	 * file.
	 */

	private void doFinish(String containerName, IPath location, IProgressMonitor monitor) throws CoreException {
		// create a sample file
		monitor.beginTask("Creating " + containerName, 2);

		monitor.worked(1);

		final Archetype archetype = new Archetype();
		archetype.setGroupId("org.glassmaker");
		archetype.setArtifactId("org.glassmaker.archetype.basic");
		archetype.setVersion("0.0.1");
		ProjectParameters params = parametersPage.getParams();

		final String groupId = params.getGroupId();
		final String artifactId = params.getArtifactId();
		final String version = params.getVersion();
		final String javaPackage = params.getPackageName();
		final Properties properties = params.getProperties();
		properties.setProperty("oauth2callbackurl", properties.getProperty(ProjectWizardParametersPage.O_AUTH_CALLBACK));
		properties.setProperty("clientid", properties.getProperty(ProjectWizardParametersPage.CLIENT_ID));
		properties.setProperty("clientsecret", properties.getProperty(ProjectWizardParametersPage.CLIENT_SECRET));

		List<IProject> projects = MavenPlugin.getProjectConfigurationManager().createArchetypeProjects(location, archetype, groupId, artifactId, version, javaPackage, properties, importConfiguration, monitor);

	}

	/**
	 * We will accept the selection in the workbench to see if we can initialize
	 * from it.
	 *
	 * @see IWorkbenchWizard#init(IWorkbench, IStructuredSelection)
	 */
	public void init(IWorkbench workbench, IStructuredSelection selection) {
		this.selection = selection;
	}
}


package com.github.mrcritical.ironcache.internal.serializers;

import java.io.IOException;

import org.joda.time.DateTimeZone;
import org.joda.time.LocalDateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;

/**
 * Deserialize a Joda {@link LocalDateTime}.
 *
 * @author pjarrell
 *
 */
public class JodaLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {

	private final DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss'Z'").withZone(
			DateTimeZone.UTC);

	/*
	 * (non-Javadoc)
	 *
	 * @see org.codehaus.jackson.map.JsonDeserializer#deserialize(org.codehaus
	 * .jackson .JsonParser, org.codehaus.jackson.map.DeserializationContext)
	 */
	@Override
	public LocalDateTime deserialize(final JsonParser parser, final DeserializationContext context) throws IOException,
	JsonProcessingException {
		return formatter.parseLocalDateTime(parser.getText());
	}

}


/*******************************************************************************
 * <copyright>
 *
 * Copyright (c) 2014 Eteration A.S.
 * All rights reserved.
 * 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.
 *
 *
 *     Derivative Works
 *     Parts of this program are derived from content from Eclipse Foundation
 *     that are made available under the terms of the Eclipse Public License v1.0.
 *      http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Naci Dai, Eteration A.S. - initial API, implementation and documentation
 *
 * </copyright>
 *
 *******************************************************************************/
package org.glassmaker.ui.editor.wizards;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

import com.ibm.icu.lang.UCharacter;

/**
 * Wizard page responsible for gathering information about the Maven2 artifact
 * when an archetype is being used to create a project (thus the class name
 * pun).
 */
public class ProjectWizardParametersPage extends WizardPage {

	public static final String O_AUTH_CALLBACK = "OAuth Callback";
	public static final String CLIENT_SECRET = "Client Secret";
	public static final String CLIENT_ID = "Client Id";
	public static final String DEFAULT_VERSION = "0.0.1-SNAPSHOT"; //$NON-NLS-1$
	public static final String DEFAULT_PACKAGE = "foo"; //$NON-NLS-1$

	Table propertiesTable;

	TableViewer propertiesViewer;

	final public static String KEY_PROPERTY = "key"; //$NON-NLS-1$

	final public static int KEY_INDEX = 0;

	final public static String VALUE_PROPERTY = "value"; //$NON-NLS-1$

	final public static int VALUE_INDEX = 1;

	/** group id text field */
	protected Combo groupIdCombo;

	/** artifact id text field */
	protected Combo artifactIdCombo;

	/** version text field */
	protected Combo versionCombo;

	/** package text field */
	protected Combo packageCombo;

	protected Button removeButton;

	private boolean isUsed = true;

	protected Set<String> requiredProperties;

	protected Set<String> optionalProperties;

	/** shows if the package has been customized by the user */
	protected boolean packageCustomized = false;

	private ProjectParameters params;

	/** Creates a new page. */
	public ProjectWizardParametersPage() {

		super("wizardPage");
		setTitle("Glassmaker Project Parameters");
		setDescription("Glassmaker Project Parameters");
		setPageComplete(false);

		requiredProperties = new HashSet<String>();
		optionalProperties = new HashSet<String>();
	}

	/** Creates page controls. */
	public void createControl(Composite parent) {
		Composite composite = new Composite(parent, SWT.NULL);
		composite.setLayout(new GridLayout(3, false));

		createArtifactGroup(composite);
		createPropertiesGroup(composite);
		setArchetype() ;
		validate();

		setControl(composite);

	}

	private void createArtifactGroup(Composite parent) {

		Label groupIdlabel = new Label(parent, SWT.NONE);
		groupIdlabel.setText("Group Id:");

		groupIdCombo = new Combo(parent, SWT.BORDER);
		groupIdCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
		groupIdCombo.setData("name", "groupId"); //$NON-NLS-1$ //$NON-NLS-2$
		groupIdCombo.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				updateJavaPackage();
				validate();
			}
		});

		Label artifactIdLabel = new Label(parent, SWT.NONE);
		artifactIdLabel.setText("Artifact Id:");

		artifactIdCombo = new Combo(parent, SWT.BORDER);
		artifactIdCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
		artifactIdCombo.setData("name", "artifactId"); //$NON-NLS-1$ //$NON-NLS-2$
		artifactIdCombo.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				updateJavaPackage();
				validate();
			}
		});

		Label versionLabel = new Label(parent, SWT.NONE);
		versionLabel.setText("Version");

		versionCombo = new Combo(parent, SWT.BORDER);
		GridData gd_versionCombo = new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1);
		gd_versionCombo.widthHint = 150;
		versionCombo.setLayoutData(gd_versionCombo);
		versionCombo.setText(DEFAULT_VERSION);
		versionCombo.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				validate();
			}
		});

		Label packageLabel = new Label(parent, SWT.NONE);
		packageLabel.setText("Package");

		packageCombo = new Combo(parent, SWT.BORDER);
		packageCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
		packageCombo.setData("name", "package"); //$NON-NLS-1$ //$NON-NLS-2$
		packageCombo.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				if (!packageCustomized && !packageCombo.getText().equals(getDefaultJavaPackage())) {
					packageCustomized = true;
				}
				validate();
			}
		});
	}

	private void createPropertiesGroup(Composite composite) {
		Label propertiesLabel = new Label(composite, SWT.NONE);
		propertiesLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
		propertiesLabel.setText("Properties");

		propertiesViewer = new TableViewer(composite, SWT.BORDER | SWT.FULL_SELECTION);
		propertiesTable = propertiesViewer.getTable();
		propertiesTable.setLinesVisible(true);
		propertiesTable.setHeaderVisible(true);
		propertiesTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 2));

		TableColumn propertiesTableNameColumn = new TableColumn(propertiesTable, SWT.NONE);
		propertiesTableNameColumn.setWidth(130);
		propertiesTableNameColumn.setText("Name");

		TableColumn propertiesTableValueColumn = new TableColumn(propertiesTable, SWT.NONE);
		propertiesTableValueColumn.setWidth(230);
		propertiesTableValueColumn.setText("Value");

		propertiesViewer.setColumnProperties(new String[] { KEY_PROPERTY, VALUE_PROPERTY });

		propertiesViewer.setCellEditors(new CellEditor[] { new TextCellEditor(propertiesTable, SWT.NONE), new TextCellEditor(propertiesTable, SWT.NONE) });
		propertiesViewer.setCellModifier(new ICellModifier() {
			public boolean canModify(Object element, String property) {
				return true;
			}

			public void modify(Object element, String property, Object value) {
				if (element instanceof TableItem) {
					((TableItem) element).setText(getTextIndex(property), String.valueOf(value));
					validate();
				}
			}

			public Object getValue(Object element, String property) {
				if (element instanceof TableItem) {
					return ((TableItem) element).getText(getTextIndex(property));
				}
				return null;
			}
		});

	}

	/**
	 * Validates the contents of this wizard page.
	 *

	 * Feedback about the validation is given to the user by displaying error
	 * messages or informative messages on the wizard page. Depending on the
	 * provided user input, the wizard page is marked as being complete or not.
	 *

	 * If some error or missing input is detected in the user input, an error
	 * message or informative message, respectively, is displayed to the user.
	 * If the user input is complete and correct, the wizard page is marked as
	 * begin complete to allow the wizard to proceed. To that end, the following
	 * conditions must be met:
	 *

	 *
The user must have provided a valid group ID.

	 *
The user must have provided a valid artifact ID.

	 *
The user must have provided a version for the artifact.

	 *

	 *

	 *
	 * @see org.eclipse.jface.dialogs.DialogPage#setMessage(java.lang.String)
	 * @see org.eclipse.jface.wizard.WizardPage#setErrorMessage(java.lang.String)
	 * @see org.eclipse.jface.wizard.WizardPage#setPageComplete(boolean)
	 */
	void validate() {
		if (isVisible()) {
			String error = validateInput();
			setErrorMessage(error);
			setPageComplete(error == null);
		}
	}

	private String validateInput() {
		String error = validateGroupIdInput(groupIdCombo.getText().trim());
		if (error != null) {
			return error;
		}

		error = validateArtifactIdInput(artifactIdCombo.getText().trim());
		if (error != null) {
			return error;
		}

		String versionValue = versionCombo.getText().trim();
		if (versionValue.length() == 0) {
			return "Must have a version";
		}
		// TODO: check validity of version?

		String packageName = packageCombo.getText();
		if (packageName.trim().length() != 0) {
			if (!Pattern.matches("[A-Za-z_$][A-Za-z_$\\d]*(?:\\.[A-Za-z_$][A-Za-z_$\\d]*)*", packageName)) { //$NON-NLS-1$
				return "Must have a valid Java package name";
			}
		}

//		// validate project name
//		IStatus nameStatus = validateProjectName(getModel());
//		if (!nameStatus.isOK()) {
//			return "Project name is not valid";
//		}

		return null;
	}

	/** Ends the wizard flow chain. */
	public IWizardPage getNextPage() {
		return null;
	}

	public void setArchetype() {
		propertiesTable.removeAll();
		requiredProperties.clear();
		optionalProperties.clear();

		Properties properties = new Properties();
		properties.setProperty(CLIENT_ID, "ENTER YOUR GOOGLE API CLIENT ID");
		properties.setProperty(CLIENT_SECRET, "ENTER YOUR GOOGLE API CLIENT SECRET");
		properties.setProperty(O_AUTH_CALLBACK,"https://localhost:8888/oauth/callback" );

		if (properties != null) {
			for (Iterator<Map.Entry<Object, Object>> it = properties.entrySet().iterator(); it.hasNext();) {
				Map.Entry<?, ?> e = it.next();
				String key = (String) e.getKey();
				addTableItem(key, (String) e.getValue());
				optionalProperties.add(key);
			}
		}

	}

	/**
	 * @param key
	 * @param value
	 */
	TableItem addTableItem(String key, String value) {
		TableItem item = new TableItem(propertiesTable, SWT.NONE);
		item.setData(item);
		item.setText(KEY_INDEX, key);
		item.setText(VALUE_INDEX, value == null ? "" : value); //$NON-NLS-1$
		return item;
	}

	/**
	 * Updates the properties when a project name is set on the first page of
	 * the wizard.
	 */
	public void setProjectName(String projectName) {
		if (artifactIdCombo.getText().equals(groupIdCombo.getText())) {
			groupIdCombo.setText(projectName);
		}
		artifactIdCombo.setText(projectName);
		packageCombo.setText("org." + projectName.replace('-', '.')); //$NON-NLS-1$
		validate();
	}

	/**
	 * Updates the properties when a project name is set on the first page of
	 * the wizard.
	 */
	public void setParentProject(String groupId, String artifactId, String version) {
		groupIdCombo.setText(groupId);
		versionCombo.setText(version);
		validate();
	}

	/** Enables or disables the artifact id text field. */
	public void setArtifactIdEnabled(boolean b) {
		artifactIdCombo.setEnabled(b);
	}

	/** Returns the package name. */
	public String getJavaPackage() {
		if (packageCombo.getText().length() > 0) {
			return packageCombo.getText();
		}
		return getDefaultJavaPackage();
	}

	/** Updates the package name if the related fields changed. */
	protected void updateJavaPackage() {
		if (packageCustomized) {
			return;
		}

		String defaultPackageName = getDefaultJavaPackage();
		packageCombo.setText(defaultPackageName);
	}

	/** Returns the default package name. */
	protected String getDefaultJavaPackage() {
		return ProjectWizardParametersPage.getDefaultJavaPackage(groupIdCombo.getText().trim(), artifactIdCombo.getText().trim());
	}

	public void setUsed(boolean isUsed) {
		this.isUsed = isUsed;
	}

	public boolean isPageComplete() {
		return !isUsed || super.isPageComplete();
	}

	/** Loads the group value when the page is displayed. */
	public void setVisible(boolean visible) {
		super.setVisible(visible);

		boolean shouldValidate = false;

		if (visible) {

			if (groupIdCombo.getText().length() == 0 && groupIdCombo.getItemCount() > 0) {
				groupIdCombo.setText(groupIdCombo.getItem(0));
				packageCombo.setText(getDefaultJavaPackage());
				packageCustomized = false;
			}

			if (shouldValidate) {
				validate();
			}
		}
	}

	public Properties getProperties() {
		if (propertiesViewer.isCellEditorActive()) {
			propertiesTable.setFocus();
		}
		Properties properties = new Properties();
		for (int i = 0; i < propertiesTable.getItemCount(); i++) {
			TableItem item = propertiesTable.getItem(i);
			properties.put(item.getText(KEY_INDEX), item.getText(VALUE_INDEX));
		}
		return properties;
	}

	public int getTextIndex(String property) {
		return KEY_PROPERTY.equals(property) ? KEY_INDEX : VALUE_INDEX;
	}

	public static String getDefaultJavaPackage(String groupId, String artifactId) {
		StringBuffer sb = new StringBuffer(groupId);

		if (sb.length() > 0 && artifactId.length() > 0) {
			sb.append('.');
		}

		sb.append(artifactId);

		if (sb.length() == 0) {
			sb.append(DEFAULT_PACKAGE);
		}

		boolean isFirst = true;
		StringBuffer pkg = new StringBuffer();
		for (int i = 0; i < sb.length(); i++) {
			char c = sb.charAt(i);
			if (c == '-') {
				pkg.append('_');
				isFirst = false;
			} else {
				if (isFirst) {
					if (UCharacter.isJavaIdentifierStart(c)) {
						pkg.append(c);
						isFirst = false;
					}
				} else {
					if (c == '.') {
						pkg.append('.');
						isFirst = true;
					} else if (UCharacter.isJavaIdentifierPart(c)) {
						pkg.append(c);
					}
				}
			}
		}

		return pkg.toString();
	}

	private boolean isVisible() {
		return getControl() != null && getControl().isVisible();
	}

	protected String validateArtifactIdInput(String text) {
		return validateIdInput(text, true);
	}

	protected String validateGroupIdInput(String text) {
		return validateIdInput(text, false);
	}

	private String validateIdInput(String text, boolean artifact) {
		if (text == null || text.length() == 0) {
			return artifact ? "Must have an Artifact Id" : "Must have a Group Id";
		}

		if (text.contains(" ")) { //$NON-NLS-1$
			return artifact ? "Artifact Id cannot have spaces" : "Group Id cannot have spaces";
		}

		IStatus nameStatus = ResourcesPlugin.getWorkspace().validateName(text, IResource.PROJECT);
		if (!nameStatus.isOK()) {
			return artifact ? "Invalid Artifact Id" : "Invalid Group Id";
		}

		if (!text.matches("[A-Za-z0-9_\\-.]+")) { //$NON-NLS-1$
			return artifact ? "Invalid Artifact Id" : "Invalid Group Id";
		}
        params = initProjectParameters();
		return null;
	}

	public ProjectParameters initProjectParameters() {

		ProjectParameters params = new ProjectParameters();
		params.setGroupId(groupIdCombo.getText());
		params.setArtifactId(artifactIdCombo.getText());
		params.setVersion(versionCombo.getText());
		params.setProperties(getProperties());
		params.setPackageName(getJavaPackage());

		return params;

	}

	public ProjectParameters getParams() {
		return params;
	}

	public void setParams(ProjectParameters params) {
		this.params = params;
	}

}


package org.criteria4jpa.criterion;

import org.criteria4jpa.Criteria;
import org.criteria4jpa.impl.CriteriaQueryBuilder;

/**
 *
 * Class representing a "not" restriction.
 * It is recommended to use the static factory methods of
 * {@link Restrictions} to created instances of this class.
 *
 * @see Restrictions#not(Criterion)
 *
 * @author Christian Kaltepoth
 *
 */
public class NotExpression implements Criterion {

  private final Criterion criterion;

  /**
   * Creates a "not" expression
   *
   * @param criterion the restriction to negate
   */
  public NotExpression(Criterion criterion) {
    this.criterion = criterion;
  }

  /*
   * @see org.criteria4jpa.criterion.Criterion#toQueryString(org.criteria4jpa.Criteria, org.criteria4jpa.impl.CriteriaQueryBuilder)
   */
  public String toQueryString(Criteria criteria, CriteriaQueryBuilder queryBuilder) {
    return "NOT "+criterion.toQueryString(criteria, queryBuilder);
  }

  /*
   * @see org.criteria4jpa.criterion.Criterion#getParameterValues()
   */
  public Object[] getParameterValues() {
    return criterion.getParameterValues();
  }

}


package org.criteria4jpa.impl;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import org.criteria4jpa.Criteria;
import org.criteria4jpa.criterion.Criterion;
import org.criteria4jpa.order.Order;
import org.criteria4jpa.projection.Projection;

public class CriteriaImpl implements Criteria {

  // basic stuff
  private final EntityManager entityManager;
  private final String entityName;
  private final String alias;

  // properties
  private final List<MetaEntry<Criterion>> criterionList = new ArrayList<MetaEntry<Criterion>>();
  private final List<MetaEntry<Order>> orderList = new ArrayList<MetaEntry<Order>>();
  private final List<MetaEntry<PathFetchMode>> fetchTypeList = new ArrayList<MetaEntry<PathFetchMode>>();
  private final List<SubCriteriaImpl> subcriteriaList = new ArrayList<SubCriteriaImpl>();
  private MetaEntry<Projection> projectionEntry;
  private Integer maxResults;
  private Integer firstResult;

  public CriteriaImpl(EntityManager entityManager, String name) {
    this(entityManager, name, null);
  }

  public CriteriaImpl(EntityManager entityManager, String name, String alias) {
    this.entityManager = entityManager;
    this.entityName = name;
    this.alias = alias;
  }

  /*
   * internal
   */

  public void addOrder(Criteria criteria, Order order) {
    this.orderList.add(new MetaEntry<Order>(criteria, order));
  }

  public Criteria add(Criteria criteria, Criterion criterion) {
    this.criterionList.add(new MetaEntry<Criterion>(criteria, criterion));
    return this;
  }

  protected Criteria createCriteria(Criteria parent, String associationPath,
      String alias, JoinType joinType) {
    SubCriteriaImpl subcriteria =
      new SubCriteriaImpl(this, parent, associationPath, alias, joinType);
    subcriteriaList.add(subcriteria);
    return subcriteria;
  }

  protected void setProjection(Criteria criteria, Projection projection) {
    projectionEntry = new MetaEntry<Projection>(criteria, projection);
  }

  public Criteria setFetchMode(Criteria criteria, String relativePath, FetchMode fetchMode) {
    this.fetchTypeList.add( new MetaEntry<PathFetchMode>(criteria,
        new PathFetchMode(relativePath, fetchMode)) );
    return this;
  }

  /*
   * interface impl
   */

  public Criteria add(Criterion criterion) {
    add(this, criterion);
    return this;
  }

  public Criteria addOrder(Order order) {
    addOrder(this, order);
    return this;
  }

  public Criteria createCriteria(String associationPath) {
    return createCriteria(this, associationPath, null, JoinType.INNER_JOIN);
  }

  public Criteria createCriteria(String associationPath, JoinType joinType) {
    return createCriteria(this, associationPath, null, joinType);
  }

  public Criteria createCriteria(String associationPath, String alias) {
    return createCriteria(this, associationPath, alias, JoinType.INNER_JOIN);
  }

  public Criteria createCriteria(String associationPath, String alias, JoinType joinType) {
    return createCriteria(this, associationPath, alias, joinType);
  }

  public Criteria setProjection(Projection projection) {
    setProjection(this, projection);
    return this;
  }

  public Criteria setFirstResult(int firstResult) {
    this.firstResult = Integer.valueOf(firstResult);
    return this;
  }

  public Criteria setMaxResults(int maxResults) {
    this.maxResults = Integer.valueOf(maxResults);
    return this;
  }

  public Criteria setFetchMode(String relativePath, FetchMode fetchMode) {
    this.setFetchMode(this, relativePath, fetchMode);
    return this;
  }

  /*
   * execute query
   */

  @SuppressWarnings("unchecked")
  public <E> List<E> getResultList() {
    return buildQuery().getResultList();
  }

  @SuppressWarnings("unchecked")
  public <E> E getSingleResult() {
    return (E) buildQuery().getSingleResult();
  }

  @SuppressWarnings("unchecked")
  public <E> E getSingleResultOrNull() {
    try {
      return (E) getSingleResult();
    } catch (NoResultException e) {
      return null;
    }
  }

  /*
   * debugging
   */

  @Override
  public String toString() {
    return new CriteriaQueryBuilder(this).createQueryDebugString();
  }

  /*
   * internal stuff
   */

  private Query buildQuery() {
    CriteriaQueryBuilder queryBuilder = new CriteriaQueryBuilder(this);
    return queryBuilder.createQuery(entityManager);
  }

  /*
   * getter
   */

  public Integer getMaxResults() {
    return maxResults;
  }

  public Integer getFirstResult() {
    return firstResult;
  }

  public String getEntityName() {
    return entityName;
  }

  public String getAlias() {
    return alias;
  }

  public List<MetaEntry<Criterion>> getCriterionList() {
    return criterionList;
  }

  public List<MetaEntry<Order>> getOrderList() {
    return orderList;
  }

  public List<SubCriteriaImpl> getSubcriteriaList() {
    return subcriteriaList;
  }

  public MetaEntry<Projection> getProjectionEntry() {
    return projectionEntry;
  }

  public List<MetaEntry<PathFetchMode>> getFetchTypeList() {
    return fetchTypeList;
  }

}


/*******************************************************************************
 * <copyright>
 *
 * Copyright (c) 2014 Eteration A.S.
 * All rights reserved.
 * 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.
 *
 * Contributors:
 *    Naci Dai, Eteration A.S. - initial API, implementation and documentation
 *
 * </copyright>
 *
 *******************************************************************************/
package org.glassmaker.spring.oauth;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.stereotype.Component;

import com.google.api.client.auth.oauth2.AuthorizationCodeFlow;
import com.google.api.client.http.GenericUrl;

@Component("oAuth2EntryPoint")
public class OAuth2EntryPoint implements AuthenticationEntryPoint, InitializingBean {
	// ~ Static fields/initializers
	// =====================================================================================

	private static final Log logger = LogFactory.getLog(OAuth2EntryPoint.class);

	// ~ Instance fields
	// ================================================================================================
	@Value("${callback}")
	private String callbackUrl;

	@Autowired
	private OAuth2Util oAuth2Util;

	private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

	public OAuth2EntryPoint() {
	}

	public void afterPropertiesSet() throws Exception {
	}

	/**
	 * Performs the redirect (or forward) to the login form URL.
	 */
	public void commence(HttpServletRequest req, HttpServletResponse resp, AuthenticationException authException) throws IOException, ServletException {

		String redirectUrl = null;
		logger.debug("No auth context found. Kicking off a new auth flow.");

		AuthorizationCodeFlow flow = oAuth2Util.newAuthorizationCodeFlow();
		GenericUrl url = flow.newAuthorizationUrl().setRedirectUri(getCallbackUrl());
		url.set("approval_prompt", "force");
		redirectUrl = url.build();
		redirectStrategy.sendRedirect(req, resp, redirectUrl);

	}

	public String getCallbackUrl() {
		return callbackUrl;
	}

	public void setCallbackUrl(String callbackUrl) {
		this.callbackUrl = callbackUrl;
	}

	public OAuth2Util getoAuth2Util() {
		return oAuth2Util;
	}

	public void setoAuth2Util(OAuth2Util oAuth2Util) {
		this.oAuth2Util = oAuth2Util;
	}
}


package org.criteria4jpa.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.criteria4jpa.Criteria;
import org.criteria4jpa.Criteria.FetchMode;
import org.criteria4jpa.Criteria.JoinType;
import org.criteria4jpa.criterion.Criterion;
import org.criteria4jpa.order.Order;
import org.criteria4jpa.projection.Projection;
import org.criteria4jpa.util.QueryLogHelper;
import org.criteria4jpa.util.StringUtils;

public class CriteriaQueryBuilder {

  private final Logger queryLogger = Logger.getLogger("org.criteria4jpa.queries");

  private final CriteriaImpl rootCriteria;

  private final Map<Criteria, String> criterionToAliasMap =
    new HashMap<Criteria, String>();

  private int positionalParameterCounter = 1;

  public CriteriaQueryBuilder(CriteriaImpl rootCriteria) {
    this.rootCriteria = rootCriteria;
    buildCriterionToAliasMap();
  }

  private void buildCriterionToAliasMap() {

    // counter to create unique aliases
    int counter = 1;

    // add alias for root criteria
    String rootAlias = rootCriteria.getAlias();
    if(rootAlias == null) {
      rootAlias = StringUtils.generateAlias(rootCriteria.getEntityName(), counter++, "root");
    }
    criterionToAliasMap.put(rootCriteria, rootAlias);

    // process subcriteria
    for( SubCriteriaImpl subcriteria : rootCriteria.getSubcriteriaList() ) {
      String alias = subcriteria.getAlias();
      if(alias == null) {
        String lastPathComponent = StringUtils.getLastPathComponent(subcriteria.getPath());
        alias = StringUtils.generateAlias(lastPathComponent, counter++, "sub");
      }
      String old = criterionToAliasMap.put(subcriteria, alias);
      if(old != null) {
        throw new IllegalStateException("Duplicated alias definition for: "+alias);
      }
    }
  }

  public Query createQuery(EntityManager entityManager) {

    // create for generate query
    String queryString = createQueryString();
    Query query = entityManager.createQuery(queryString);

    // set max results
    if(rootCriteria.getMaxResults() != null) {
      query.setMaxResults(rootCriteria.getMaxResults());
    }

    // set first result
    if(rootCriteria.getFirstResult() != null) {
      query.setFirstResult(rootCriteria.getFirstResult());
    }

    // get ordered list of query parameters
    List<Object> parameterValues = getQueryParametersAsList();

    // position
    int paramPosition = 1;

    // loop over all values
    for(Object value : parameterValues) {
      query.setParameter(paramPosition++, value);
    }

    // log query
    if( queryLogger.isLoggable(Level.FINE) ) {
      queryLogger.fine( QueryLogHelper.createQueryLogMessage(queryString, parameterValues) );
    }

    return query;
  }

  /**
   * Creates a human-readable representation of the query that will be created
   * from this builder
   */
  public String createQueryDebugString() {

    // create query
    String queryString = createQueryString();

    // create list of parameters
    List<Object> parameterValues = getQueryParametersAsList();

    // create debug string
    return QueryLogHelper.createQueryLogMessage(queryString, parameterValues);

  }

  public String createQueryString() {

    // build query string
    StringBuilder builder = new StringBuilder();

    builder.append( createSelectClause() );
    builder.append( ' ' );
    builder.append( createFromClause() );
    builder.append( ' ' );
    builder.append( createWhereClause() );
    builder.append( ' ' );
    builder.append( createGroupByClause() );
    builder.append( ' ' );
    builder.append( createOrderByClause() );

    return builder.toString().trim();
  }

  private String createSelectClause() {

    // begin with SELECT
    StringBuilder builder = new StringBuilder();
    builder.append( "SELECT " );

    if(rootCriteria.getProjectionEntry() != null) {

      // get required objects to render projection
      Projection projection = rootCriteria.getProjectionEntry().getEntry();
      Criteria projectionCriteria = rootCriteria.getProjectionEntry().getCriteria();

      // render projection
      builder.append( projection.toQueryString(projectionCriteria, this) );

    }
    else {
      // if no projection exists, we just select the root entity
      builder.append( getRequiredAlias(rootCriteria) );
    }

    return builder.toString();
  }

  private String createFromClause() {

    // builder
    StringBuilder builder = new StringBuilder();

    // root criteria
    builder.append("FROM ");
    builder.append( rootCriteria.getEntityName() );
    builder.append(' ');
    builder.append( getRequiredAlias(rootCriteria) );

    // process all subcriteria
    for(SubCriteriaImpl subcriteria : rootCriteria.getSubcriteriaList()) {

      // absolute join path
      String joinPath = getAbsolutePath(subcriteria.getParent(), subcriteria.getPath());

      // append correct join expression
      if(subcriteria.getJoinType() == JoinType.INNER_JOIN) {
        builder.append(" JOIN ");
      }
      else if(subcriteria.getJoinType() == JoinType.LEFT_OUTER_JOIN) {
        builder.append(" LEFT JOIN ");
      }

      builder.append( joinPath );
      builder.append(' ');
      builder.append( getRequiredAlias(subcriteria) );
    }

    for(MetaEntry<PathFetchMode> fetchModeEntry : rootCriteria.getFetchTypeList()) {

      PathFetchMode pathFetchMode = fetchModeEntry.getEntry();

      if(pathFetchMode.getFetchMode() == FetchMode.DEFAULT) {
        continue;
      }

      // absolute join path
      String joinPath = getAbsolutePath(fetchModeEntry.getCriteria(), pathFetchMode.getRelativePath());

      // append correct join expression
      if(pathFetchMode.getFetchMode() == FetchMode.INNER_FETCH_JOIN) {
        builder.append(" JOIN FETCH ");
      }
      else if(pathFetchMode.getFetchMode() == FetchMode.LEFT_OUTER_FETCH_JOIN) {
        builder.append(" LEFT JOIN FETCH ");
      }
      else {
        throw new IllegalStateException("Unsupported FetchType: "+pathFetchMode.getFetchMode());
      }

      builder.append( joinPath );

      // 4.4.5.3: No alias allowed for fetch joins
    }

    // return result
    return builder.toString();
  }

  private String createWhereClause() {

    // iterate over all criterion of this criteria
    Iterator<MetaEntry<Criterion>> iter = rootCriteria.getCriterionList().iterator();

    // abort if not criterion
    if( !iter.hasNext() ) {
      return "";
    }

    // String Builder for where clause
    StringBuilder builder = new StringBuilder("WHERE ");

    while(iter.hasNext()) {

      MetaEntry<Criterion> entry = iter.next();
      Criteria criteria = entry.getCriteria();
      Criterion criterion = entry.getEntry();

      // let criterion build its JPQL string
      builder.append( criterion.toQueryString(criteria, this) );

      // append AND if more restrictions follow
      if(iter.hasNext()) {
        builder.append( " AND " );
      }
    }

    return builder.toString();
  }

  private String createGroupByClause() {

    if(rootCriteria.getProjectionEntry() != null) {

      // get required objects to render projection
      Projection projection = rootCriteria.getProjectionEntry().getEntry();
      Criteria projectionCriteria = rootCriteria.getProjectionEntry().getCriteria();

      // render group by properties
      String groupByString = projection.toGroupByString(projectionCriteria, this);
      if( groupByString != null && groupByString.trim().length() > 0) {
        return "GROUP BY "+groupByString.trim();
      }

    }

    // no group by
    return "";

  }

  private String createOrderByClause() {

    // get iterator for order objects
    Iterator<MetaEntry<Order>> iter = rootCriteria.getOrderList().iterator();

    // no orders added -> exit here
    if( !iter.hasNext() ) {
      return "";
    }

    // add ORDER BY keywords
    StringBuilder builder = new StringBuilder("ORDER BY ");

    // loop over all order objects
    while( iter.hasNext() ) {

      // current order object
      MetaEntry<Order> orderEntry = iter.next();
      Order order = orderEntry.getEntry();
      Criteria criteria = orderEntry.getCriteria();

      // create JPQL string
      String orderByString = order.toQueryString(criteria, this);
      builder.append( orderByString );

      // append comma if more to write
      if( iter.hasNext() ) {
        builder.append(", ");
      }

    }

    return builder.toString();

  }

  /**
   * Creates an ordered list of all parameter values registered at
   * the root criteria.
   *
   * @return list of parameter values
   */
  private List<Object> getQueryParametersAsList() {

    // iterate over all restrictions of this criteria
    Iterator<MetaEntry<Criterion>> iter = rootCriteria.getCriterionList().iterator();

    // result list
    List<Object> result = new ArrayList<Object>();

    // loop over all criterion
    while(iter.hasNext()) {

      // the current criterion
      Criterion criterion = iter.next().getEntry();

      // get the values to set
      Object[] parameterValues = criterion.getParameterValues();

      // null should be ignores
      if(parameterValues == null) {
        continue;
      }

      // set all parameters
      for(Object value : parameterValues) {
        result.add( value );
      }

    }

    return result;
  }

  public String getAbsolutePath(Criteria c, String relativePath) {
    return getRequiredAlias(c)+"."+relativePath;
  }

  public String getRequiredAlias(Criteria criteria) {
    String alias = criterionToAliasMap.get(criteria);
    if(alias == null) {
      throw new IllegalStateException("Cannot find alias for criteria: "+criteria);
    }
    return alias;
  }

  public CriteriaImpl getRootCriteria() {
    return rootCriteria;
  }

  /**
   * Creates a positional parameter for a JPQL query.
   */
  public String createPositionalParameter() {
    return "?" + (positionalParameterCounter++);
  }

}


/*******************************************************************************
 * <copyright>
 *
 * Copyright (c) 2014 Eteration A.S.
 * All rights reserved.
 * 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.
 *
 *
 *     Derivative Works
 *     Parts of this program are derived from content from Eclipse Foundation
 *     that are made available under the terms of the Eclipse Public License v1.0.
 *      http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Naci Dai, Eteration A.S. - initial API, implementation and documentation
 *
 * </copyright>
 *
 *******************************************************************************/
package org.glassmaker.ui.editor.preferences;

import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
import org.eclipse.jface.preference.IPreferenceStore;

import org.glassmaker.ui.GlassmakerUIPlugin;

/**
 * Class used to initialize default preference values.
 */
public class PreferenceInitializer extends AbstractPreferenceInitializer {

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
	 */
	public void initializeDefaultPreferences() {
		IPreferenceStore store = GlassmakerUIPlugin.getDefault().getPreferenceStore();

		store.setDefault(PreferenceConstants.CLIENT_ID,"YOU_MUST_PROVIDE_A_CLIENT_ID");
		store.setDefault(PreferenceConstants.CLIENT_SECRET,"YOU_MUST_PROVIDE_A_CLIENT_SECRET");
	}

}