package hudson.plugins.dry.parser;

import hudson.plugins.analysis.core.AnnotationParser;
import hudson.plugins.analysis.util.ContextHashCode;
import hudson.plugins.analysis.util.model.FileAnnotation;
import hudson.plugins.dry.parser.cpd.CpdParser;
import hudson.plugins.dry.parser.simian.SimianParser;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import org.apache.commons.io.IOUtils;
import org.apache.xerces.parsers.SAXParser;

import com.google.common.collect.Sets;

import edu.umd.cs.findbugs.annotations.SuppressWarnings;

/**
 * Registry for duplication parsers.
 *
 * @author Ulli Hafner
 */
public class DuplicationParserRegistry implements AnnotationParser {
    private static final long serialVersionUID = -8114361417348412242L;
    @SuppressWarnings("SE")
    private final List<AbstractDryParser> parsers = new ArrayList<AbstractDryParser>();
    private String workspacePath;
    private final String defaultEncoding;

    /** Property of SAX parser factory. */
    private static final String SAX_DRIVER_PROPERTY = "org.xml.sax.driver";

   /**
     * Creates a new instance of {@link DuplicationParserRegistry}.
     *
     * @param highThreshold
     *            minimum number of duplicate lines for high priority warnings
     * @param normalThreshold
     *            minimum number of duplicate lines for normal priority warnings
     * @param defaultEncoding
     *            default encoding of the files
     */
    public DuplicationParserRegistry(final int normalThreshold, final int highThreshold, final String defaultEncoding) {
        this.defaultEncoding = defaultEncoding;
        parsers.add(new CpdParser(highThreshold, normalThreshold));
        parsers.add(new SimianParser(highThreshold, normalThreshold));
    }

    /**
     * Creates a new instance of {@link DuplicationParserRegistry}.
     *
     * @param highThreshold
     *            minimum number of duplicate lines for high priority warnings
     * @param normalThreshold
     *            minimum number of duplicate lines for normal priority warnings
     * @param workspacePath
     *            path to the workspace files
     * @param defaultEncoding
     *            default encoding of the files
     */
    public DuplicationParserRegistry(final int normalThreshold, final int highThreshold,
            final String workspacePath, final String defaultEncoding) {
        this(normalThreshold, highThreshold, defaultEncoding);

        this.workspacePath = workspacePath;
    }

    /** {@inheritDoc} */
    public Collection<FileAnnotation> parse(final File file, final String moduleName) throws InvocationTargetException {
        String oldProperty = System.getProperty(SAX_DRIVER_PROPERTY);
        if (oldProperty != null) {
            System.setProperty(SAX_DRIVER_PROPERTY, SAXParser.class.getName());
        }

        FileInputStream inputStream = null;
        try {
            for (AbstractDryParser parser : parsers) {
                inputStream = new FileInputStream(file);
                if (parser.accepts(inputStream)) {
                    IOUtils.closeQuietly(inputStream);
                    inputStream = new FileInputStream(file);
                    Collection<DuplicateCode> result = parser.parse(inputStream, moduleName);
                    createLinkNames(result);
                    Set<FileAnnotation> warnings = Sets.newHashSet();
                    warnings.addAll(result);
                    ContextHashCode hashCode = new ContextHashCode();
                    for (FileAnnotation duplication : warnings) {
                        duplication.setContextHashCode(hashCode.create(duplication.getFileName(), duplication.getPrimaryLineNumber(),
                                defaultEncoding));
                    }

                    return warnings;
                }
            }
            throw new IOException("No parser found for duplicated code results file " + file.getAbsolutePath());
        }
        catch (IOException exception) {
            throw new InvocationTargetException(exception);
        }
        finally {
            IOUtils.closeQuietly(inputStream);
            if (oldProperty != null) {
                System.setProperty(SAX_DRIVER_PROPERTY, oldProperty);
            }
        }
    }

    /**
     * For each duplicate code annotation that does not have a package name
     * (i.e., for non Java sources), a link name is generated.
     *
     * @param result the annotations
     */
    private void createLinkNames(final Collection<DuplicateCode> result) {
        if (workspacePath != null) {
            for (FileAnnotation duplication : result) {
                duplication.setPathName(workspacePath);
            }
        }
    }
}


package hudson.plugins.dry;

import hudson.util.FormValidation;

/**
 * Validates the number of lines thresholds.
 *
 * @author Ulli Hafner
 */
public class ThresholdValidation {
    /** Minimum number of duplicate lines for a warning with priority high. */
    static final int DEFAULT_HIGH_THRESHOLD = 50;
    /** Minimum number of duplicate lines for a warning with priority normal. */
    static final int DEFAULT_NORMAL_THRESHOLD = 25;

    /**
     * Performs on-the-fly validation on threshold for high warnings.
     *
     * @param highThreshold
     *            the threshold for high warnings
     * @param normalThreshold
     *            the threshold for normal warnings
     * @return the validation result
     */
    public FormValidation validateHigh(final String highThreshold, final String normalThreshold) {
        return validate(highThreshold, normalThreshold, Messages.DRY_ValidationError_HighThreshold());
    }

    /**
     * Performs on-the-fly validation on threshold for normal warnings.
     *
     * @param highThreshold
     *            the threshold for high warnings
     * @param normalThreshold
     *            the threshold for normal warnings
     * @return the validation result
     */
    public FormValidation validateNormal(final String highThreshold, final String normalThreshold) {
        return validate(highThreshold, normalThreshold, Messages.DRY_ValidationError_NormalThreshold());
    }

    /**
     * Performs on-the-fly validation on thresholds for high and normal warnings.
     *
     * @param highThreshold
     *            the threshold for high warnings
     * @param normalThreshold
     *            the threshold for normal warnings
     * @param message
     *            the validation message
     * @return the validation result
     */
    private FormValidation validate(final String highThreshold, final String normalThreshold, final String message) {
        try {
            int high = Integer.parseInt(highThreshold);
            int normal = Integer.parseInt(normalThreshold);
            if (isValid(normal, high)) {
                return FormValidation.ok();
            }
        }
        catch (NumberFormatException exception) {
            // ignore and return failure
        }
        return FormValidation.error(message);
    }

    /**
     * Returns the minimum number of duplicate lines for a warning with priority
     * high.
     *
     * @param normalThreshold
     *            the normal threshold
     * @param highThreshold
     *            the high threshold
     * @return the minimum number of duplicate lines for a warning with priority
     *         high
     */
    public int getHighThreshold(final int normalThreshold, final int highThreshold) {
        if (!isValid(normalThreshold, highThreshold)) {
            return DEFAULT_HIGH_THRESHOLD;
        }
        return highThreshold;
    }

    private boolean isValid(final int normalThreshold, final int highThreshold) {
        return !(highThreshold <= 0 || normalThreshold <= 0 || highThreshold <= normalThreshold);
    }

    /**
     * Returns the minimum number of duplicate lines for a warning with priority
     * normal.
     *
     * @param normalThreshold
     *            the normal threshold
     * @param highThreshold
     *            the high threshold
     * @return the minimum number of duplicate lines for a warning with priority
     *         normal
     */
    public int getNormalThreshold(final int normalThreshold, final int highThreshold) {
        if (!isValid(normalThreshold, highThreshold)) {
            return DEFAULT_NORMAL_THRESHOLD;
        }
        return normalThreshold;
    }
}


package com.azaptree.services.command.http;

/*
 * #%L
 * AZAPTREE-COMMAND-HTTP-SERVICE
 * %%
 * Copyright (C) 2012 - 2013 AZAPTREE.COM
 * %%
 * 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 java.io.OutputStream;

import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBException;

import org.apache.commons.chain.Context;
import org.springframework.util.Assert;

import com.azaptree.services.command.impl.CommandSupport;
import com.azaptree.wadl.Method;
import com.azaptree.wadl.Resource;
import com.google.common.base.Optional;

/**
 * Context must be of type WebCommandContext<T, V>
 *
 * @author alfio
 *
 * @param <T>
 *            request message class
 * @param <V>
 *            response message class
 */
public abstract class WebRequestCommand<T, V> extends CommandSupport {

	protected final Class<T> requestClass;
	protected final Class<V> responseClass;

	/**
	 * No request or response message is required.
	 *
	 */
	public WebRequestCommand() {
		this(null, null);
	}

	/**
	 *
	 *
	 * @param requestClass
	 *            OPTIONAL
	 * @param responseClass
	 *            OPTIONAL
	 * @throws JAXBException
	 */
	public WebRequestCommand(final Class<T> requestClass, final Class<V> responseClass) {
		this.requestClass = requestClass;
		this.responseClass = responseClass;
	}

	/**
	 *
	 * @param name
	 *            REQUIRED
	 * @param requestClass
	 *            OPTIONAL
	 * @param responseClass
	 *            OPTIONAL
	 */
	public WebRequestCommand(final String name, final Class<T> requestClass, final Class<V> responseClass) {
		super(name);
		this.requestClass = requestClass;
		this.responseClass = responseClass;
	}

	/**
	 * Creates a relative resource for this command. The resource path is set to the command name, and a POST method is added:
	 *
	 *
		<resource path="command-name">
            <method name="POST"></method>
        </resource>
	 *
	 *
	 * Override this method to further describe the REST API for the is command. For example:
	 *
	 *

	 *
you may want add documentation, via Doc elements

	 *
describe further HTTP error responses

	 *

	 *
	 * @return
	 */
	public Resource createCommandResourceWadl() {
		final Resource resource = new Resource();
		resource.setPath(getName());

		final Method method = new Method();
		method.setName("POST");
		resource.getMethodOrResource().add(method);

		definePostMethodWadl(method);

		return resource;
	}

	/**
	 * Override to define the POST method
	 *
	 * @param method
	 */
	protected void definePostMethodWadl(final Method method) {
		// no-op
	}

	@SuppressWarnings("unchecked")
	@Override
	protected boolean executeCommand(final Context ctx) {
		return executeCommand((WebCommandContext<T, V>) ctx);
	}

	protected abstract boolean executeCommand(WebCommandContext<T, V> ctx);

	/**
	 * Map generate an XML schema or JSON schema.
	 *
	 * @param os
	 */
	public void generateSchema(final OutputStream os) {
		// no-op
	}

	public Optional<Class<T>> getRequestClass() {
		if (requestClass == null) {
			return Optional.absent();
		}
		return Optional.of(requestClass);
	}

	public Optional<Class<V>> getResponseClass() {
		if (responseClass == null) {
			return Optional.absent();
		}
		return Optional.of(responseClass);
	}

	/**
	 * Knows how to marshal the the message to the HTTP response outputstream
	 *
	 * @param httpResponse
	 * @param message
	 */
	protected abstract void writeResponseMessage(final HttpServletResponse httpResponse, final Object message);

	protected void writeResponseMessage(final WebCommandContext<T, V> ctx) {
		Assert.notNull(ctx, "ctx is required");
		writeResponseMessage(ctx.getHttpServletResponse(), ctx.getResponseMessage());
	}

}


package com.github.rosmith.service.scanner;

import com.github.rosmith.service.annotation.Handler;
import com.github.rosmith.service.fetcher.Fetcher;
import com.github.rosmith.service.handler.IHandler;
import com.github.rosmith.service.protocol.Protocol;
import com.github.rosmith.service.proxy.ServiceProxy;
import com.github.rosmith.service.proxy.ServiceProxy.DefaultServiceProxy;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import com.google.common.reflect.ClassPath;

/**
 * @author Ronald Smith, Djomkam Yotedje
 */
public class HandlerScanner {

	private static final String HANDLER_PACKAGE = "com.github.rosmith.service.handler.impl";

	/**
	 * Scans the package "module.application.service.handler" for classes
	 * annotated with "@Handler(protocol=...)". For every class found with this
	 * annotation an instance of this class is created per Java-Reflection and
	 * added to the result list of handlers.
	 *
	 * @return A list of instantiated and proxied handler.
	 * @throws Exception
	 *             Reflection-Exception
	 */
	public static <T, D> List<IHandler<T, D>> scan() throws Exception {
		return scan(false);
	}

	@SuppressWarnings("unchecked")
	private static <T, D> List<IHandler<T, D>> scan(boolean proxy)
			throws Exception {
		List<IHandler<T, D>> handlers = new ArrayList<IHandler<T, D>>();

		Set<Class<?>> types = scan(HANDLER_PACKAGE, Handler.class);

		for (String handlerPackage : Fetcher.handlerPackages()) {
			for (Class<?> clzz : scan(handlerPackage, Handler.class)) {
				if (!types.contains(clzz)) {
					types.add(clzz);
				}
			}
		}

		for (Class<?> type : types) {
			Handler annotation = type.getAnnotation(Handler.class);
			Constructor<?> c = type.getDeclaredConstructor(String.class);
			c.setAccessible(true);

			Protocol.verifyIfExists(annotation.protocol());

			IHandler<T, D> handler = (IHandler<T, D>) c.newInstance(annotation
					.protocol());
			if (proxy) {
				handler = ServiceProxy.activateProxy(handler, DefaultServiceProxy.class);
			}
			handlers.add(handler);
		}

		return handlers;
	}

	public static Set<Class<?>> scan(String packageName) {
		Set<Class<?>> set = new HashSet<Class<?>>();
		ClassPath classpath = null;
		try {
			classpath = ClassPath.from(HandlerScanner.class.getClassLoader());
		} catch (IOException e) {
			e.printStackTrace();
		}
		for (ClassPath.ClassInfo classInfo : classpath
				.getTopLevelClasses(packageName)) {
			try {
				Class<?> clzz = Class.forName(packageName+"."+classInfo.getSimpleName());
				set.add(clzz);
			} catch (ClassNotFoundException e) {
			}
		}
		return set;
	}

	public static Set<Class<?>> scan(String packageName, Class<? extends Annotation> annotation) {
		Set<Class<?>> result = scan(packageName);
		result = result.stream().filter(c -> {
			Annotation anno = c.getDeclaredAnnotation(annotation);
			return anno != null && anno.annotationType() != null;
		}).collect(Collectors.toSet());
		return result;
	}

	public static void main(String[] args) {
		scan(HANDLER_PACKAGE);
	}

	/**
	 * Scans the package "module.application.service.handler" for classes
	 * annotated with "@Handler(protocol=...)". For every class found with this
	 * annotation an instance of this class is created per Java-Reflection and
	 * added to the result list of handlers. The difference between this method
	 * and the scan-Method is that this method creates a proxy-object for each
	 * created instance. The reason for doing this is that upon calling any
	 * method of these proxied-instances, a small logic has to be done after
	 * this method has returned and just before the caller receives the result.
	 *
	 * @return A list of instantiated and proxied handler.
	 * @throws Exception
	 *             Reflection-Exception
	 */
	public static <T, D> List<IHandler<T, D>> proxyScan() throws Exception {
		return scan(true);
	}

}


/**
 * Copyright (C) 2012 Ness Computing, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.nesscomputing.migratory.loader;

import java.io.IOException;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Pattern;

import com.google.common.collect.Sets;
import com.google.common.io.Resources;

import com.nesscomputing.migratory.MigratoryException;
import com.nesscomputing.migratory.MigratoryException.Reason;

/**
 * Loads arbitrary files from a file: URI.
 */
public class JarLoader implements MigrationLoader
{
    private final Charset charset;

    public JarLoader(final Charset charset)
    {
        this.charset = charset;
    }

    @Override
    public boolean accept(final URI uri)
    {
        return uri != null && "jar".equals(uri.getScheme());
    }

    @Override
    public Collection<URI> loadFolder(final URI location, final String searchPattern) throws IOException
    {
        final Pattern pattern = (searchPattern == null) ? null : Pattern.compile(searchPattern);

        final String path = location.getSchemeSpecificPart();
        final int bangIndex = path.indexOf("!");
        if (bangIndex > 0) {
            final String jarPath = path.substring(5, bangIndex); // strip out jar:/, all the way to the bang.
            final String basePath = "jar:" + path.substring(0, bangIndex + 2);
            final String locationPath = path.substring(bangIndex + 2); // skip over !/
            final JarFile jar = new JarFile(jarPath); // URI.getPath is decoded.

            try {
                final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
                final Set<URI> results = Sets.newHashSet();

                while(entries.hasMoreElements()) {
                    final JarEntry entry = entries.nextElement();

                    String entryName = entry.getName();
                    if (entryName.startsWith(locationPath)) { //filter according to the path
                        entryName = entryName.substring(locationPath.length() + 1);
                        int checkSubdir = entryName.indexOf("/");
                        // Skip Directories
                        if ((!entryName.isEmpty() && checkSubdir < 0) && (pattern == null || pattern.matcher(entryName).matches())) { // NOPMD
                            results.add(URI.create(basePath + entry.getName()));
                        }
                    }
                }
                return results;
            }
            finally {
                jar.close();
            }
        }
        else {
            throw new MigratoryException(Reason.INTERNAL, "Can not parse jar URI '%s!", location);
        }
    }

    /**
     * This method loads a file from a file:/... URI. This is probably not what you are looking for.
     */
    @Override
    public String loadFile(final URI fileUri) throws IOException
    {
        return Resources.toString(fileUri.toURL(), charset);
    }
}


/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.deephacks.tools4j.cli;

import org.deephacks.tools4j.cli.Command.Argument;
import org.deephacks.tools4j.cli.Command.Option;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Utility code are kept here to avoid distorting readability of other
 * classes with code that is irrelevant to their domain.
 */
final class Utils {
    /** name of the validator class */
    public static final String VALIDATOR_CLASSNAME = "org.deephacks.tools4j.cli.Validator";
    /** API class for JSR 303 1.0 bean validation */
    public static final String JSR303_1_0_CLASSNAME = "javax.validation.Validation";
    /** API class for JSR 303 1.1 bean validation, class only exist in 1.1 */
    public static final String JSR303_1_1_CLASSNAME = "javax.validation.metadata.MethodDescriptor";

    /** the instance of the Validator object */
    private static Object validator;
    /** new line character */
    public static final String NEWLINE = System.getProperty("line.separator");
    static final String AVAILABLE_CMDS_MSG = "Available commands are:";

    static Object newInstance(String className) {
        try {
            Class<?> type = Thread.currentThread().getContextClassLoader().loadClass(className);
            Class<?> enclosing = type.getEnclosingClass();
            if (enclosing == null) {
                Constructor<?> c = type.getDeclaredConstructor();
                c.setAccessible(true);
                return type.cast(c.newInstance());
            }
            Object o = enclosing.newInstance();
            Constructor<?> cc = type.getDeclaredConstructor(enclosing);
            cc.setAccessible(true);
            return type.cast(cc.newInstance(o));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    static String stripTrailingWhitespace(String str) {
        if (str == null || "".equals(str.trim())) {
            return "";
        }
        StringBuffer sb = new StringBuffer(str);
        int pos = str.length() - 1;
        while (true) {
            if (Character.isWhitespace(sb.charAt(pos))) {
                sb.deleteCharAt(pos--);
            } else {
                break;
            }
        }
        return sb.toString();
    }

    /**
     * Validate that the method parameters if Bean Validation 1.1 is available
     * on classpath.
     */
    static void validateArgs(List<Object> args, Object instance, Method m, Command cmd) {
        if (!onClasspath(JSR303_1_1_CLASSNAME)) {
            return;
        }
        try {
            Object validator = getValidator();
            Method validate = validator.getClass().getMethod("validateArgs", List.class,
                    Object.class, Method.class, Command.class);
            validate.invoke(validator, args, instance, m, cmd);
        } catch (InvocationTargetException e) {
            if (e.getTargetException() instanceof RuntimeException) {
                throw (RuntimeException) e.getCause();
            }
            throw new RuntimeException(e.getCause());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Validate that the options if Bean Validation is available on classpath.
     */
    static void validateOpts(Object instance) {
        if (!onClasspath(JSR303_1_0_CLASSNAME)) {
            return;
        }
        try {
            Object validator = getValidator();
            Method validate = validator.getClass().getMethod("validateOpts", Object.class);
            validate.invoke(validator, instance);
        } catch (InvocationTargetException e) {
            if (e.getTargetException() instanceof RuntimeException) {
                throw (RuntimeException) e.getTargetException();
            }
            throw new RuntimeException(e.getTargetException());
        } catch (RuntimeException e) {
            throw e;
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    private static Object getValidator() throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        if (validator == null) {
            ClassLoader cl = Thread.currentThread().getContextClassLoader();
            validator = cl.loadClass(VALIDATOR_CLASSNAME).newInstance();

        }
        return validator;
    }

    /**
     * Checks to see if JSR303 implementation is
     * available on classpath.
     */
    static boolean onClasspath(String className) {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        try {
            cl.loadClass(className);
        } catch (ClassNotFoundException e) {
            return false;
        }
        return true;
    }

    public static HashMap<String, String> parseParamsJavadoc(String javadoc) {
        if (javadoc == null || "".equals(javadoc.trim())) {
            return new HashMap<String, String>();
        }
        final HashMap<String, String> params = new HashMap<String, String>();
        final StringBuffer sb = new StringBuffer(javadoc.trim());
        int pos;
        while ((pos = sb.indexOf("@param")) > -1) {
            sb.delete(0, pos + 1);
            int end = sb.indexOf(" ");
            sb.delete(0, end + 1);
            end = sb.indexOf(" ");
            String param = sb.substring(0, end);
            sb.delete(0, end + 1);
            int next = sb.indexOf("@");
            if (next == -1) {
                next = sb.length();
            }
            params.put(param, Utils.stripTrailingWhitespace(sb.substring(0, next)));
            sb.delete(0, next);
        }
        return params;
    }

    public static String parseJavadoc(String javadoc) {
        if (javadoc == null || "".equals(javadoc.trim())) {
            return "";
        }
        javadoc = javadoc.trim();
        int pos = javadoc.indexOf('@');
        if (pos < 0) {
            return javadoc;
        }
        javadoc = javadoc.substring(0, pos);
        return Utils.stripTrailingWhitespace(javadoc);
    }

    public static void printAvailableCommandsHelp(Map<String, Command> commands) {
        StringBuilder sb = new StringBuilder();
        sb.append(AVAILABLE_CMDS_MSG).append(NEWLINE).append(NEWLINE);
        int maxlength = getMaxCmdLength(commands);
        for (Command cmd : commands.values()) {
            StringBuilder sentence = new StringBuilder();
            for (char c : cmd.getDoc().toCharArray()) {
                sentence.append(c);
                if (c == '.') {
                    break;
                }
            }
            sb.append(String.format(" %-" + maxlength + "s : %s %n", cmd.getCommand(), sentence));
        }
        sb.append(NEWLINE).append(" Try `[command] --help' for more information.");
        System.out.println(sb.toString());
    }

    public static void printCommandHelp(Command cmd) {
        StringBuilder sb = new StringBuilder();

        sb.append("usage: ").append(cmd.getCommand());
        if (cmd.getOptions().size() > 0) {
            sb.append(" [OPTION]... ");
        }

        for (Argument arg : cmd.getArguments()) {
            sb.append(arg.getName()).append(" ");
        }
        int optlength = getMaxOptLength(cmd.getOptions());

        sb.append(NEWLINE).append(NEWLINE);
        sb.append(" ").append(cmd.getDoc()).append(NEWLINE).append(NEWLINE);
        sb.append("OPTIONS").append(NEWLINE).append(NEWLINE);
        for (Option opt : cmd.getOptions()) {
            StringBuilder optstr = new StringBuilder();
            optstr.append(" ");
            optstr.append("-").append(opt.getShortName()).append(",");
            optstr.append("--").append(opt.getLongName());
            sb.append(String.format(" %-" + (optlength + 3) + "s : ", optstr.toString()));

            List<String> lines = splitAndIndent(opt.getDoc(), optlength + 6);
            for (String line : lines) {
                sb.append(line).append(NEWLINE);
            }
            sb.append(NEWLINE);
        }

        if (cmd.getArguments().size() > 0) {
            sb.append("ARGUMENTS").append(NEWLINE);
        }
        int arglength = getMaxArgLength(cmd.getArguments());
        sb.append(NEWLINE);
        for (Argument arg : cmd.getArguments()) {
            sb.append(String.format(" %-" + arglength + "s : ", arg.getName()));
            List<String> lines = splitAndIndent(arg.getDoc(), arglength + 3);
            for (String line : lines) {
                sb.append(line).append(NEWLINE);
            }
            sb.append(NEWLINE);
        }

        System.out.println(sb.toString());
    }

    private static List<String> splitAndIndent(String str, int indentLength) {
        String[] split = str.split(System.getProperty("line.separator"));
        List<String> lines = new ArrayList<String>();
        for (int i = 0; i < split.length; i++) {
            if (i == 0) {
                // dont indent first line, it already is
                lines.add(split[i]);
                continue;
            }
            StringBuilder sb = new StringBuilder();
            for (int j = 0; j < indentLength; j++) {
                sb.append(' ');
            }
            sb.append(split[i]);
            lines.add(sb.toString());
        }
        return lines;
    }

    private static int getMaxCmdLength(Map<String, Command> cmds) {
        int length = 0;
        for (Command cmd : cmds.values()) {
            int l = cmd.getCommand().length();
            if (l > length) {
                length = l;
            }
        }
        return length;
    }

    private static int getMaxArgLength(List<Argument> args) {
        int length = 0;
        for (Argument arg : args) {
            int l = arg.getName().length();
            if (l > length) {
                length = l;
            }
        }
        return length;
    }

    private static int getMaxOptLength(List<Option> args) {
        int length = 0;
        for (Option opt : args) {
            int l = opt.getLongName().length() + opt.getShortName().length() + 3;
            if (l > length) {
                length = l;
            }
        }
        return length;
    }
}


package hudson.plugins.dry;

import hudson.Extension;
import hudson.plugins.analysis.core.ReporterDescriptor;
import hudson.util.FormValidation;

import org.kohsuke.stapler.QueryParameter;

/**
 * Descriptor for the class {@link DryReporter}. Used as a singleton. The
 * class is marked as public so that it can be accessed from views.
 *
 * @author Ulli Hafner
 */
@Extension(ordinal = 100, optional = true) // NOCHECKSTYLE
public class DryReporterDescriptor extends ReporterDescriptor {
    /** Validates the thresholds user input. */
    private static final ThresholdValidation THRESHOLD_VALIDATION = new ThresholdValidation();

    /**
     * Creates a new instance of {@link DryReporterDescriptor}.
     */
    public DryReporterDescriptor() {
        super(DryReporter.class, new DryDescriptor());
    }

    /**
     * Performs on-the-fly validation on threshold for high warnings.
     *
     * @param highThreshold
     *            the threshold for high warnings
     * @param normalThreshold
     *            the threshold for normal warnings
     * @return the validation result
     */
    public FormValidation doCheckHighThreshold(@QueryParameter final String highThreshold, @QueryParameter final String normalThreshold) {
        return THRESHOLD_VALIDATION.validateHigh(highThreshold, normalThreshold);
    }

    /**
     * Performs on-the-fly validation on threshold for normal warnings.
     *
     * @param highThreshold
     *            the threshold for high warnings
     * @param normalThreshold
     *            the threshold for normal warnings
     * @return the validation result
     */
    public FormValidation doCheckNormalThreshold(@QueryParameter final String highThreshold, @QueryParameter final String normalThreshold) {
        return THRESHOLD_VALIDATION.validateNormal(highThreshold, normalThreshold);
    }
}


/**
 * Copyright (C) 2012 Ness Computing, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.nesscomputing.migratory.loader;

import java.io.IOException;
import java.net.URI;
import java.util.Collection;
import java.util.List;

import com.google.common.collect.Lists;

import com.nesscomputing.migratory.MigratoryException;
import com.nesscomputing.migratory.MigratoryException.Reason;

/**
 * Loads a resource from a remote or local location.
 */
public class LoaderManager implements MigrationLoader
{
    private List<MigrationLoader> loaders = Lists.newArrayList();

    public void addLoader(MigrationLoader loader)
    {
        loaders.add(loader);
    }

    public List<MigrationLoader> getLoaders()
    {
        return loaders;
    }

    /**
     * Returns true if this loader accepts the URI.
     */
    public boolean accept(final URI uri)
    {
        for (final MigrationLoader loader : loaders) {
            if (loader.accept(uri)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Loads a collection of URIs from a given location. The resulting
     * URIs may or may not loadable using this loader (e.g. a classpath folder
     * can contain File or Jar URIs.
     */
    public Collection<URI> loadFolder(final URI folderUri, final String pattern)
    {
        try {
            for (final MigrationLoader loader : loaders) {
                if (loader.accept(folderUri)) {
                    return loader.loadFolder(folderUri, pattern);
                }
            }
            return null;
        }
        catch (IOException ioe) {
            throw new MigratoryException(Reason.INTERNAL, ioe);
        }
    }

    /**
     * Load a file from an URI.
     */
    public String loadFile(final URI fileUri)
    {
        try {
            for (final MigrationLoader loader : loaders) {
                if (loader.accept(fileUri)) {
                    return loader.loadFile(fileUri);
                }
            }
            return null;
        }
        catch (IOException ioe) {
            throw new MigratoryException(Reason.INTERNAL, ioe);
        }
    }
}


/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.deephacks.tools4j.cli;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.deephacks.tools4j.cli.Command.XmlCommands;

/**
 * This is the central class used to execute commands.
 */
public final class CliMain {
    /** commands available */
    private final Map<String, Command> commands = new HashMap<String, Command>();
    /** cli command parser */
    private GNUishParser p;
    /** raw terminal arguments */
    private String[] terminalArgs;

    /**
     * Executed when the user runs:
     *
     * $ java -jar tools4j-cli.jar
     *
     * @param args command arguments
     */
    public static void main(String[] args) {
        CliMain main = new CliMain(args);
        main.run();
    }

    public CliMain(String terminalArgs[]) {
        this.terminalArgs = terminalArgs;
    }

    /**
     * @see run()
     * @param command Instance of a class that defines at least one command.
     */
    public void run(Object command) {
        final List<Command> cmds = Command.create(command);
        for (Command cmd : cmds) {
            cmd.setInstance(command);
            commands.put(cmd.getCommand(), cmd);
        }
        run();
    }

    /**
     * Start evaluating the user input and eventually execute the command
     * requested by the user.
     *
     * @throws RuntimeException Any runtime exceptions thrown by either this
     * library or user commands will fall through and thrown from this method.
     */
    public void run() throws RuntimeException {
        if (terminalArgs == null) {
            terminalArgs = new String[0];
        }
        p = GNUishParser.parse(terminalArgs);
        readCommands();
        if (p.getCommand() == null || "".equals(p.getCommand())) {
            Utils.printAvailableCommandsHelp(commands);
            return;
        }

        final Command cmd = commands.get(p.getCommand());
        if (cmd == null) {
            throw CliException.COMMAND_NOT_FOUND(p.getCommand());
        }
        if (p.help()) {
            Utils.printCommandHelp(cmd);
            return;
        }
        try {
            cmd.execute(p);
        } catch (Exception e) {
            if (p.debug()) {
                e.printStackTrace();
            }
            if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            }
        }
    }

    /**
     * Find all commands available on classpath.
     */
    private void readCommands() {
        try {
            final Enumeration<URL> urls = Thread.currentThread().getContextClassLoader()
                    .getResources(XmlCommands.FILEPATH);
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                InputStream in = url.openStream();
                for (Command command : XmlCommands.fromXml(in)) {
                    commands.put(command.getCommand(), command);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}


package com.azaptree.services.http.handler;

/*
 * #%L
 * AZAPTREE-HTTP-SERVICE
 * %%
 * Copyright (C) 2012 - 2013 AZAPTREE.COM
 * %%
 * 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 java.io.IOException;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.Executor;

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

import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

public abstract class AsyncHttpHandlerSupport extends AbstractHandler {
	protected Logger log = LoggerFactory.getLogger(getClass());

	protected final Executor executor;

	public AsyncHttpHandlerSupport(final Executor executor) {
		super();
		Assert.notNull(executor, "executor is required");
		this.executor = executor;
	}

	@Override
	public void handle(final String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response)
	        throws IOException, ServletException {
		final Map<String, Object> context = preProcess(target, baseRequest, request, response);
		if (baseRequest.isHandled()) {
			log.debug("request was handled by preProcess()");
			return;
		}

		executor.execute(new Runnable() {

			@Override
			public void run() {
				process(target, context);
			}

		});

		postProcess(target, baseRequest, request, response);
		if (baseRequest.isHandled()) {
			log.debug("request was handled by preProcess()");
			return;
		}

		baseRequest.setHandled(true);
	}

	/**
	 * The purpose of this methods is to allow the Handler to return an HTTP response. For example, return an appropriate response that the request was accepted
	 * per the requirements of a REST API.
	 *
	 * *** NOTE: to indicate that this method handled the request, set Request.handled to true: baseRequest.setHandled(true);
	 *
	 * @param target
	 * @param baseRequest
	 * @param request
	 * @param response
	 * @throws IOException
	 * @throws ServletException
	 */
	protected void postProcess(final String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response)
	        throws IOException, ServletException {
		// NOOP
	}

	/**
	 * Validate the request and extract any data from the HTTP request that will be required to process the request asynchronously.
	 *
	 * If the request is invalid, then handle the request appropriately.
	 *
	 * *** NOTE: to indicate that this method handled the request, set Request.handled to true: baseRequest.setHandled(true);
	 *
	 * @param target
	 * @param baseRequest
	 * @param request
	 * @param response
	 * @return
	 */
	protected Map<String, Object> preProcess(final String target, final Request baseRequest, final HttpServletRequest request,
	        final HttpServletResponse response) throws IOException, ServletException {
		return Collections.emptyMap();
	}

	/**
	 *
	 * @param context
	 *            data that is extracted from the request
	 */
	protected abstract void process(final String target, final Map<String, Object> context);

}


/**
 * Copyright (C) 2012 Ness Computing, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.nesscomputing.migratory;

import java.nio.charset.Charset;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import org.apache.commons.lang3.StringUtils;
import org.skife.config.ConfigurationObjectFactory;
import org.skife.config.SimplePropertyConfigSource;
import org.skife.jdbi.v2.DBI;
import org.skife.jdbi.v2.IDBI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.nesscomputing.migratory.MigratoryException.Reason;
import com.nesscomputing.migratory.dbsupport.DbSupport;
import com.nesscomputing.migratory.dbsupport.DbSupportFactory;
import com.nesscomputing.migratory.information.DefaultMigrationInformationStrategy;
import com.nesscomputing.migratory.information.MigrationInformationStrategy;
import com.nesscomputing.migratory.jdbi.MigratoryDBI;
import com.nesscomputing.migratory.loader.ClasspathLoader;
import com.nesscomputing.migratory.loader.FileLoader;
import com.nesscomputing.migratory.loader.JarLoader;
import com.nesscomputing.migratory.loader.LoaderManager;
import com.nesscomputing.migratory.loader.MetadataLoader;
import com.nesscomputing.migratory.loader.MigrationLoader;
import com.nesscomputing.migratory.locator.MetadataMigrationLocator;
import com.nesscomputing.migratory.locator.MigrationLocator;
import com.nesscomputing.migratory.metadata.MetadataInfo;
import com.nesscomputing.migratory.metadata.MetadataManager;
import com.nesscomputing.migratory.migration.MigrationPlan;
import com.nesscomputing.migratory.migration.MigrationResult.MigrationState;
import com.nesscomputing.migratory.validation.ValidationResult;

/**
 * Main facade. Application code should only deal with this class.
 */
public class Migratory implements MigratoryContext
{
    private static final Logger LOG = LoggerFactory.getLogger(Migratory.class);

    private final MigratoryConfig migratoryConfig;
    private final MigratoryDBI dbi;
    private final MigratoryDBI rootDbi;

    private final List<MigrationLocator> locators = Lists.newArrayList();
    private final LoaderManager loaderManager = new LoaderManager();
    private final Map<String, Object> defines = Maps.newHashMap();

    private MigrationInformationStrategy informationStrategy = new DefaultMigrationInformationStrategy();
    private DbSupportFactory dbSupportFactory = new DbSupportFactory();

    private volatile DbSupport dbSupport = null;
    private boolean initialized = false;

    public Migratory(final MigratoryConfig migratoryConfig, final IDBI dbi)
    {
        this.migratoryConfig = migratoryConfig;
        this.dbi = new MigratoryDBI(dbi);
        this.rootDbi = this.dbi;
    }

    public Migratory(final MigratoryConfig migratoryConfig, final IDBI dbi, final IDBI rootDbi)
    {
        this.migratoryConfig = migratoryConfig;
        this.dbi = new MigratoryDBI(dbi);
        this.rootDbi = new MigratoryDBI(rootDbi);
    }

    public Migratory(final MigratoryConfig migratoryConfig, final MigratoryDBIConfig dbiConfig, final MigratoryDBIConfig rootDbiConfig)
    throws MigratoryException
    {
        this.migratoryConfig = migratoryConfig;
        this.dbi = new MigratoryDBI(createDBI(dbiConfig));
        this.rootDbi = new MigratoryDBI(createDBI(rootDbiConfig));
    }

    public Migratory(final MigratoryConfig migratoryConfig, final MigratoryDBIConfig dbiConfig)
    throws MigratoryException
    {
        this.migratoryConfig = migratoryConfig;
        this.dbi = new MigratoryDBI(createDBI(dbiConfig));
        this.rootDbi = this.dbi;
    }

    public Migratory(final Properties properties)
    throws MigratoryException
    {
        final ConfigurationObjectFactory factory = new ConfigurationObjectFactory(new SimplePropertyConfigSource(properties));

        this.migratoryConfig = factory.build(MigratoryConfig.class);
        this.dbi = new MigratoryDBI(createDBI(factory.buildWithReplacements(MigratoryDBIConfig.class, ImmutableMap.of("_migratory", "migratory."))));
        this.rootDbi = this.dbi;
    }

    protected void init()
    {
        if (!initialized) {
            // This must be run before the init flag is set true!
            addLocator(new MetadataMigrationLocator(this));
            loaderManager.addLoader(new MetadataLoader(loaderManager));

            final Charset charset = Charset.forName(migratoryConfig.getEncoding());
            loaderManager.addLoader(new FileLoader(charset));
            loaderManager.addLoader(new JarLoader(charset));
            loaderManager.addLoader(new ClasspathLoader(loaderManager));

            this.dbSupport = dbSupportFactory.getDbSupport(dbi);

            initialized = true;

            initDbi(dbi);

            if (dbi != rootDbi) {
                initDbi(rootDbi);
            }
        }
    }

    private void initDbi(final MigratoryDBI dbi)
    {
        for (Map.Entry<String, Object> define : defines.entrySet()) {
            dbi.addDefine(define.getKey(), define.getValue());
        }

        // This must be run after the init flag is set true!
        dbi.addDefine("db_type", getDbSupport().getDatabaseType());
        dbi.addDefine("table_name", migratoryConfig.getMetadataTableName());
        dbi.addDefine("metadata_name", MetadataManager.METADATA_MIGRATION_NAME);
        dbi.addDefine("state_ok", MigrationState.OK);
    }

    /**
     * Bring the current database to the requested levels.
     */
    public Map<String, List<MetadataInfo>> dbMigrate(final MigrationPlan migrationPlan, final MigratoryOption ... options) throws MigratoryException
    {
        init();
        final InternalMigrator migrator = new InternalMigrator(this);
        return migrator.migrate(migrationPlan, options);
    }

    /**
     * Run validation on the database. Make sure that all the changes recorded in the database are the same as the ones that should be applied.
     */
    public Map<String, ValidationResult> dbValidate(final Collection<String> personalities, final MigratoryOption ... options) throws MigratoryException
    {
        init();
        final InternalValidator validator = new InternalValidator(this);
        return validator.validate(personalities, options);
    }

    /**
     * Drops all objects (tables, views, procedures, triggers, ...) in the current schema.
     */
    public void dbClean(final MigratoryOption ... options)
    {
        init();
        final InternalClean internalClean = new InternalClean(this);
        internalClean.clean(options);
    }

    /**
     * Returns the status (current version) of the database.
     */
    public Map<String, StatusResult> dbStatus(final Collection<String> personalities, final MigratoryOption ... options)
    {
        init();
        final InternalStatus internalStatus = new InternalStatus(this);
        return internalStatus.status(personalities, options);
    }

    /**
     * Returns the full history of all applied migrations.
     */
        public Map<String, List<MetadataInfo>> dbHistory(final Collection<String> personalities, final MigratoryOption ... options)
            throws MigratoryException
    {
        init();
        final InternalHistory internalHistory = new InternalHistory(this);
        return internalHistory.history(personalities, options);
    }

    /**
     * Creates and initializes the Migratory metadata table.
     *
     * Returns null if the table already exists, returns a list of migration results
     * for the migrations executed otherwise.
     */
    public List<MetadataInfo> dbInit(final MigratoryOption ... options) throws MigratoryException
    {
        init();
        final InternalInit internalInit = new InternalInit(this);
        return internalInit.init(options);
    }

    @Override
    public MigratoryDBI getDBI()
    {
        return dbi;
    }

    @Override
    public MigratoryDBI getRootDBI()
    {
        return rootDbi;
    }

    @Override
    public MigratoryConfig getConfig()
    {
        return migratoryConfig;
    }

    @Override
    public Collection<MigrationLocator> getLocators()
    {
        return locators;
    }

    @Override
    public MigrationInformationStrategy getInformationStrategy()
    {
        return informationStrategy;
    }

    @Override
    public DbSupport getDbSupport()
    {
        init();
        return dbSupport;
    }

    public LoaderManager getLoaderManager()
    {
        return loaderManager;
    }

    public Migratory addLocator(final MigrationLocator locator)
    {
        if (initialized) {
            throw new MigratoryException(Reason.INIT, "Already initialized!");
        }

        locators.add(locator);
        LOG.debug("Added {} as migration locator.", locator);
        return this;
    }

    public Migratory addLoader(final MigrationLoader loader)
    {
        if (initialized) {
            throw new MigratoryException(Reason.INIT, "Already initialized!");
        }

        loaderManager.addLoader(loader);
        LOG.debug("Added {} as migration loader.", loader);
        return this;
    }

    public Migratory addDefine(final String key, final Object value)
    {
        defines.put(key, value);
        return this;
    }

    public Migratory setInformationStategy(final MigrationInformationStrategy informationStrategy)
    {
        if (initialized) {
            throw new MigratoryException(Reason.INIT, "Already initialized!");
        }

        this.informationStrategy = informationStrategy;
        return this;
    }

    /**
     * Add support for an additional database type. The dbName is *not* the canonical name used but the
     * name returned from the database engine on the JDBC metadata!
     */
    public Migratory addDbSupport(final String dbName, final Class<? extends DbSupport> dbSupport)
    {
        if (initialized) {
            throw new MigratoryException(Reason.INIT, "Already initialized!");
        }
        dbSupportFactory.addDbSupport(dbName, dbSupport);
        return this;
    }

    protected DBI createDBI(final MigratoryDBIConfig dbiConfig) throws MigratoryException
    {
        final String driver = dbiConfig.getDBDriverClass();

        // Force the driver to be loaded.
        if (StringUtils.isNotBlank(driver)) {
            try {
                Class.forName(driver).newInstance();
                LOG.debug("Loaded Driver '{}' successfully.", driver);
            }
            catch (ClassNotFoundException cnfe) {
                throw new MigratoryException(Reason.INIT, cnfe);
            }
            catch (InstantiationException ie) {
                throw new MigratoryException(Reason.INIT, ie);
            }
            catch (IllegalAccessException iae) {
                throw new MigratoryException(Reason.INIT, iae);
            }
        }

        LOG.debug("Loading DBI, URL: {}, User: {}, Password: {}", dbiConfig.getDBUrl(),
                                                                  dbiConfig.getDBUser(),
                                                                  dbiConfig.isRevealPassword() ? dbiConfig.getDBPassword() : "XXXXX");

        return new DBI (dbiConfig.getDBUrl(), dbiConfig.getDBUser(), dbiConfig.getDBPassword());
    }
}


package com.thetransactioncompany.cors;

import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

import com.thetransactioncompany.util.PropertyParseException;
import com.thetransactioncompany.util.PropertyRetriever;

/**
 * The CORS filter configuration (typically originating from the web application
 * descriptor file {@code web.xml}). The fields become immutable (final) after
 * they are initialised.
 *
 * @author Vladimir Dzhuvinov
 * @author Luis Sala
 * @author Jared Ottley
 * @version $version$ (2012-10-19)
 */
public class CORSConfiguration {

	/**
	 * If {@code true} generic HTTP requests must be allowed to pass through
	 * the filter, else only valid and accepted CORS requests must be
	 * allowed (strict CORS filtering).
	 *
	 *
Property key: cors.allowGenericHttpRequests
	 */
	public final boolean allowGenericHttpRequests;

	/**
	 * If {@code true} the CORS filter must allow requests from any origin,
	 * else the origin whitelist {@link #allowedOrigins} must be consulted.
	 *
	 *
Property key: cors.allowOrigin (set to {@code *})
	 */
	public final boolean allowAnyOrigin;

	/**
	 * Whitelisted origins that the CORS filter must allow. Requests from
	 * origins not included here must be refused with a HTTP 403 "Forbidden"
	 * response. This property is overriden by {@link #allowAnyOrigin}.
	 *
	 *
Note: The set is of type String instead of Origin to bypass
	 * parsing of the request origins before matching, see
	 * http://lists.w3.org/Archives/Public/public-webapps/2010JulSep/1046.html
	 *
	 *
Property key: cors.allowOrigin
	 */
	public final Set<ValidatedOrigin> allowedOrigins;

	/**
	 * If {@code true} the CORS filter must allow requests from any origin
	 * which is a subdomain origin of the {@link #allowedOrigins}.
	 *
	 *
Example:
	 *
	 *
Explicitly allowed origin: {@code http://example.com}
	 *
	 *
Matches the original origin as well as any subdomain, e.g.
	 * {@code http://foo.example.com}, {@code http://bar.example.com},
	 * etc...
	 *
	 *
Property key: cors.allowSubdomains
	 */
	public final boolean allowSubdomains;

	/**
	 * Helper method to check whether requests from the specified origin
	 * must be allowed. This is done by looking up {@link #allowAnyOrigin}
	 * and {@link #allowedOrigins} as well as the {@link #allowSubdomains}
	 * setting.
	 *
	 * @param origin The origin as reported by the web client (browser),
	 *               {@code null} if unknown.
	 *
	 * @return {@code true} if the origin is allowed, else {@code false}.
	 */
	public final boolean isAllowedOrigin(final Origin origin) {

        	if (allowAnyOrigin)
                	return true;

		if (origin == null)
			return false;

		if (allowedOrigins.contains(origin))
			return true;

		else if (allowSubdomains)
			return isAllowedSubdomainOrigin(origin);

		return false;
	}

	/**
	 * Helper method to check whether the specified origin is a subdomain
	 * origin of the {@link #allowedOrigins}. This is done by looking up the
	 * origin's scheme, hostname and port and matching them with each of the
	 * {@link #allowedOrigins}.
	 *
	 *
Example:
	 *
	 *
{@code Origin: https://foo.example.com } matches
	 * {@code cors.allowedOrigin = https://example.com } whereas
	 * {@code cors.allowedOrigin = http://example.com } would not match.
	 *
	 * @param origin The origin as reported by the web client (browser),
	 *               {@code null} if unknown.
	 *
	 * @return {@code true} if the origin is an allowed subdomain origin,
	 *         else {@code false}.
	 */
	public final boolean isAllowedSubdomainOrigin(final Origin origin) {

		try {
			ValidatedOrigin validatedOrigin = origin.validate();

			String scheme = validatedOrigin.getScheme();
			String suffix = validatedOrigin.getSuffix();

			for (ValidatedOrigin allowedOrigin: allowedOrigins) {

				if (suffix.endsWith("." + allowedOrigin.getSuffix()) &&
				    scheme.equalsIgnoreCase(allowedOrigin.getScheme()))

					return true;
			}

		} catch (OriginException e) {

			return false;
		}

		return false;
	}

	/**
	 * The supported HTTP methods. Requests for methods not included here
	 * must be refused by the CORS filter with a HTTP 405 "Method not
	 * allowed" response.
	 *
	 *
Property key: cors.supportedMethods
	 */
	public final Set<HTTPMethod> supportedMethods;

	/**
	 * Helper method to check whether the specified HTTP method is
	 * supported. This is done by looking up {@link #supportedMethods}.
	 *
	 * @param method The HTTP method.
	 *
	 * @return {@code true} if the method is supported, else {@code false}.
	 */
	public final boolean isSupportedMethod(final HTTPMethod method) {

		if (supportedMethods.contains(method))
			return true;
		else
			return false;
	}

	/**
	 * The names of the supported author request headers.
	 *
	 *
Property key: cors.supportedHeaders
	 */
	public final Set<HeaderFieldName> supportedHeaders;

	/**
	 * Helper method to check whether the specified (non-simple) author
	 * request header is supported. This is done by looking up
	 * {@link #supportedHeaders}.
	 *
	 * @param header The header field name.
	 *
	 * @return {@code true} if the header is supported, else {@code false}.
	 */
	public final boolean isSupportedHeader(final HeaderFieldName header) {

        	if (supportedHeaders.contains(header))
			return true;
		else
			return false;
	}

	/**
	 * The non-simple response headers that the web browser should expose to
	 * the author of the CORS request.
	 *
	 *
Property key: cors.exposedHeaders
	 */
	public final Set<HeaderFieldName> exposedHeaders;

	/**
	 * Indicates whether user credentials, such as cookies, HTTP
	 * authentication or client-side certificates, are supported.
	 *
	 *
Property key: cors.supportsCredentials
	 */
	public final boolean supportsCredentials;

	/**
	 * Indicates how long the results of a preflight request can be cached
	 * by the web client, in seconds. If {@code -1} unspecified.
	 *
	 *
Property key: cors.maxAge
	 */
	public final int maxAge;

	/**
	 * Parses a string containing words separated by space and/or comma.
	 *
	 * @param s The string to parse. Must not be {@code null}.
	 *
	 * @return An array of the parsed words, empty if none were found.
	 */
	protected static String[] parseWords(final String s) {

		String s1 = s.trim();

		if (s1.isEmpty())
			return new String[]{};
		else
			return s1.split("\\s*,\\s*|\\s+");
	}

	/**
	 * Creates a new CORS configuration from the specified properties.
	 *
	 *
The following properties are recognised (if missing they default
	 * to the specified values):
	 *
	 *

	 *
cors.allowGenericHttpRequests {true|false} defaults to
	 *         {@code true}.
	 *
cors.allowOrigin {"*"|origin-list} defaults to {@code *}.
	 *
cors.allowSubdomains {true|false} defaults to {@code false}.
	 *
cors.supportedMethods {method-list} defaults to {@code "GET,
	 *         POST, HEAD, OPTIONS"}.
	 *
cors.supportedHeaders {header-list} defaults to empty list.
	 *
cors.exposedHeaders {header-list} defaults to empty list.
	 *
cors.supportsCredentials {true|false} defaults to
	 *         {@code true}.
	 *
cors.maxAge {int} defaults to {@code -1} (unspecified).
	 *

	 *
	 * @param props The properties. Must not be {@code null}.
	 *
	 * @throws CORSConfigurationException On a invalid property.
	 */
	public CORSConfiguration(final Properties props)
		throws CORSConfigurationException {

		try {
			PropertyRetriever pr = new PropertyRetriever(props);

			// Parse the allow generic HTTP requests option

			allowGenericHttpRequests = pr.getOptBoolean("cors.allowGenericHttpRequests", true);

			// Parse the allowed origins list

			String originSpec = pr.getOptString("cors.allowOrigin", "*").trim();

			allowedOrigins = new HashSet<ValidatedOrigin>();

			if (originSpec.equals("*")) {

				allowAnyOrigin = true;
			}
			else {
				allowAnyOrigin = false;

				String[] urls = parseWords(originSpec);

				for (String url: urls) {

					try {
						allowedOrigins.add(new Origin(url).validate());

                                	} catch (OriginException e) {

                                        	throw new PropertyParseException("Bad origin URL in property cors.allowOrigin: " + url);
                                	}
				}
			}

			// Parse the allow origin suffix matching option
			allowSubdomains = pr.getOptBoolean("cors.allowSubdomains", false);

			// Parse the supported methods list

			String methodSpec = pr.getOptString("cors.supportedMethods", "GET, POST, HEAD, OPTIONS").trim().toUpperCase();

			String[] methodNames = parseWords(methodSpec);

			supportedMethods = new HashSet<HTTPMethod>();

			for (String methodName: methodNames) {

				try {
					supportedMethods.add(HTTPMethod.valueOf(methodName));

				} catch (IllegalArgumentException e) {
					throw new PropertyParseException("Bad HTTP method name in property cors.allowMethods: " + methodName);
				}
			}

			// Parse the supported headers list

			String[] headers = parseWords(pr.getOptString("cors.supportedHeaders", ""));

			supportedHeaders = new HashSet<HeaderFieldName>();

			for (String header: headers) {

				try {
					supportedHeaders.add(new HeaderFieldName(header));

				} catch (IllegalArgumentException e) {
					throw new PropertyParseException("Bad header field name in property cors.supportedHeaders: " + header);
				}
			}

			// Parse the exposed headers list

			headers = parseWords(pr.getOptString("cors.exposedHeaders", ""));

			exposedHeaders = new HashSet<HeaderFieldName>();

			for (String header: headers) {

				try {
					exposedHeaders.add(new HeaderFieldName(header));

				} catch (IllegalArgumentException e) {
					throw new PropertyParseException("Bad header field name in property cors.exposedHeaders: " + header);
				}
			}

			// Parse the allow credentials option
			supportsCredentials = pr.getOptBoolean("cors.supportsCredentials", true);

			// Parse the max cache age of preflight requests
			maxAge = pr.getOptInt("cors.maxAge", -1);

		} catch (PropertyParseException e) {

			// Simply reformat as a more specific exception class
			// to improve stack trace clarity (config exceptions
			// are often dumped to the web client screen)

			throw new CORSConfigurationException(e.getMessage());
		}
	}
}


package com.azaptree.services.command.impl;

/*
 * #%L
 * AZAPTREE-COMMAND-SERVICE
 * %%
 * Copyright (C) 2012 AZAPTREE.COM
 * %%
 * 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.apache.commons.chain.Context;

import com.azaptree.services.command.Command;
import com.azaptree.services.command.CommandContextValidator;
import com.azaptree.services.commons.TypeReferenceKey;
import com.azaptree.services.commons.validation.ValidationException;
import com.google.common.base.Optional;

public abstract class CommandContextValidatorSupport implements CommandContextValidator {

	protected abstract void checkInput(Command command, Context ctx);

	protected abstract void checkOutput(Command command, Context ctx);

	protected void checkRequiredInputKeys(final Command command, final Context ctx) {
		final Optional<TypeReferenceKey<?>[]> keys = command.getInputKeys();
		if (!keys.isPresent()) {
			return;
		}

		for (final TypeReferenceKey<?> key : keys.get()) {
			if (key.isRequired()) {
				if (!ctx.containsKey(key)) {
					throw new ValidationException(String.format("%s  : TypeReferenceKey is required: %s", command.getName(), key));
				}
			}
		}
	}

	protected void checkRequiredOutputKeys(final Command command, final Context ctx) {
		final Optional<TypeReferenceKey<?>[]> keys = command.getOutputKeys();
		if (!keys.isPresent()) {
			return;
		}

		for (final TypeReferenceKey<?> key : keys.get()) {
			if (key.isRequired()) {
				if (!ctx.containsKey(key)) {
					throw new ValidationException(String.format("%s  : TypeReferenceKey is required: %s", command.getName(), key));
				}
			}
		}
	}

	/**
	 * Checks required input keys, and then delegates to checkInput();
	 *
	 */
	@Override
	public void validateInput(final Command command, final Context ctx) throws ValidationException {
		checkRequiredInputKeys(command, ctx);
		checkInput(command, ctx);
	}

	/**
	 * Checks required output keys, and then delegates to checkOutput();
	 *
	 */
	@Override
	public void validateOutput(final Command command, final Context ctx) throws ValidationException {
		checkRequiredOutputKeys(command, ctx);
		checkOutput(command, ctx);
	}

}


/**
 * Copyright (C) 2012 Ness Computing, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.nesscomputing.migratory.migration.sql;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Collection;
import java.util.List;

import com.google.common.collect.Lists;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.nesscomputing.migratory.MigratoryException;
import com.nesscomputing.migratory.MigratoryException.Reason;

/**
 * Sql script containing a series of statements terminated by semi-columns (;). Single-line (--) and multi-line (/* * /)
 * comments are stripped and ignored.
 */
public class SqlScript
{
    private static final Logger LOG = LoggerFactory.getLogger(SqlScript.class);

    /**
     * The default Statement delimiter.
     */
    protected static final String DEFAULT_STATEMENT_DELIMITER = ";";

    /**
     * The sql statements contained in this script.
     */
    private final Collection<SqlStatement> sqlStatements;

    public SqlScript(final String rawSql)
    {
        this.sqlStatements = parse(rawSql);
    }

    public SqlScript(final Collection<SqlStatement> sqlStatements)
    {
        this.sqlStatements = sqlStatements;
    }

    /**
     * @return The sql statements contained in this script.
     */
    public Collection<SqlStatement> getSqlStatements()
    {
        return sqlStatements;
    }

    private List<SqlStatement> parse(final String rawSql)
    {
        try {
            Reader reader = new StringReader(rawSql);
            final List<String> lines = readLines(reader);
            return linesToStatements(lines);
        }
        catch (IOException ioe) {
            throw new MigratoryException(Reason.INTERNAL, ioe, "Could not read String '%s'", rawSql);
        }
    }

    List<String> readLines(final Reader reader) throws IOException
    {
        final List<String> lines = Lists.newArrayList();

        final BufferedReader bufferedReader = new BufferedReader(reader);
        String line;

        boolean inMultilineComment = false;
        while ((line = StringUtils.trim(bufferedReader.readLine())) != null)
        {
            if (!inMultilineComment) {
                if (isCommentDirective(line) || line.startsWith("--")) {
                    LOG.trace("Ignored '{}'", line);
                    continue;
                }
                else if (line.contains("--")) {
                    lines.add(StringUtils.trim(line.substring(0, line.indexOf("--"))));
                }
                else if (line.startsWith("/*")) {
                    inMultilineComment = true;
                    LOG.trace("Start Multiline ignore at  '{}'", line);
                    if (line.endsWith("*/")) {
                    	LOG.trace("...and then immediately ending it");
                    	inMultilineComment = false;
                    }
                    continue;
                }
                else {
                    LOG.trace("Adding '{}' to output", line);
                    lines.add(line);
                }
            }
            else {
                if (line.endsWith("*/")) {
                    LOG.trace("Ending Multiline ignore at  '{}'", line);
                    inMultilineComment = false;
                }
            }
        }

        return lines;
    }

    /**
     * Turns these lines in a series of statements.
     */
    List<SqlStatement> linesToStatements(List<String> lines)
    {
        final List<SqlStatement> statements = Lists.newArrayList();
        final StringBuilder statementSql = new StringBuilder();
        int count = 0;

        String delimiter = DEFAULT_STATEMENT_DELIMITER;

        for (final String line : lines)
        {
            if (StringUtils.isBlank(line)) {
                continue;
            }

            if (statementSql.length() > 0) {
                statementSql.append(" ");
            }
            statementSql.append(line);

            final String oldDelimiter = delimiter;
            delimiter = changeDelimiterIfNecessary(statementSql.toString(), line, delimiter);
            if (!StringUtils.equals(delimiter, oldDelimiter) && isDelimiterChangeExplicit()) {
                statementSql.setLength(0);
                continue; // for
            }

            if (StringUtils.endsWith(line, delimiter)) {
                // Trim off the delimiter at the end.
                statementSql.setLength(statementSql.length() - delimiter.length());
                statements.add(new SqlStatement(count++, StringUtils.trimToEmpty(statementSql.toString())));
                LOG.debug("Found statement: {}", statementSql);

                if (!isDelimiterChangeExplicit()) {
                    delimiter = DEFAULT_STATEMENT_DELIMITER;
                }
                statementSql.setLength(0);
            }
        }

        // Catch any statements not followed by delimiter.
        if (statementSql.length() > 0) {
            statements.add(new SqlStatement(count++, StringUtils.trimToEmpty(statementSql.toString())));
        }

        return statements;
    }

    /**
     * Checks whether this line in the sql script indicates that the statement delimiter will be different from the
     * current one. Useful for database-specific stored procedures and block constructs.
     */
    protected String changeDelimiterIfNecessary(final String statement, final String line, final String delimiter)
    {
        return delimiter;
    }

    /**
     * @return {@code true} if this database uses an explicit delimiter change statement. {@code false} if a delimiter
     *         change is implied by certain statements.
     */
    protected boolean isDelimiterChangeExplicit()
    {
        return false;
    }

    /**
     * Checks whether this line is in fact a directive disguised as a comment.
     */
    protected boolean isCommentDirective(String line) {
        return false;
    }
}


/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 */
package org.incode.module.note.dom.impl.notablelink;

import java.util.List;

import javax.inject.Inject;

import org.joda.time.LocalDate;

import org.apache.isis.applib.annotation.DomainService;
import org.apache.isis.applib.annotation.NatureOfService;
import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.applib.query.QueryDefault;
import org.apache.isis.applib.services.bookmark.Bookmark;
import org.apache.isis.applib.services.bookmark.BookmarkService;
import org.apache.isis.applib.services.registry.ServiceRegistry2;
import org.apache.isis.applib.services.repository.RepositoryService;
import org.apache.isis.applib.services.title.TitleService;

import org.incode.module.note.dom.impl.note.Note;

@DomainService(
        nature = NatureOfService.DOMAIN,
        repositoryFor = NotableLink.class
)
public class NotableLinkRepository {

    //region > findByNote (programmatic)
    @Programmatic
    public NotableLink findByNote(final Note note) {
        return repositoryService.firstMatch(
                new QueryDefault<>(NotableLink.class,
                        "findByNote",
                        "note", note));
    }
    //endregion

    //region > findByNotable (programmatic)
    @Programmatic
    public List<NotableLink> findByNotable(final Object notable) {
        if(notable == null) {
            return null;
        }
        final Bookmark bookmark = bookmarkService.bookmarkFor(notable);
        if(bookmark == null) {
            return null;
        }
        final String notableStr = bookmark.toString();
        return repositoryService.allMatches(
                new QueryDefault<>(NotableLink.class,
                        "findByNotable",
                        "notableStr", notableStr));
    }
    //endregion

    //region > findByNotableAndCalendarName (programmatic)

    /**
     * Each notable can only have one note per calendar, thus this method returns a single object rather than a list.
     */
    @Programmatic
    public NotableLink findByNotableAndCalendarName(
            final Object notable,
            final String calendarName) {
        if(notable == null) {
            return null;
        }
        if(calendarName == null) {
            return null;
        }
        final Bookmark bookmark = bookmarkService.bookmarkFor(notable);
        if(bookmark == null) {
            return null;
        }
        final String notableStr = bookmark.toString();
        return repositoryService.firstMatch(
                new QueryDefault<>(NotableLink.class,
                        "findByNotableAndCalendarName",
                        "notableStr", notableStr,
                        "calendarName", calendarName));
    }
    //endregion

    //region > findByNotableInDateRange (programmatic)
    @Programmatic
    public List<NotableLink> findByNotableInDateRange(
            final Object notable,
            final LocalDate startDate,
            final LocalDate endDate) {
        if(notable == null) {
            return null;
        }
        final Bookmark bookmark = bookmarkService.bookmarkFor(notable);
        if(bookmark == null) {
            return null;
        }
        if(startDate == null) {
            return null;
        }
        if(endDate == null) {
            return null;
        }
        final String notableStr = bookmark.toString();
        return repositoryService.allMatches(
                new QueryDefault<>(NotableLink.class,
                        "findByNotableInDateRange",
                        "notableStr", notableStr,
                        "startDate", startDate,
                        "endDate", endDate));
    }
    //endregion

    //region > createLink (programmatic)
    @Programmatic
    public NotableLink createLink(
            final Note note,
            final Object notable) {

        final Class<? extends NotableLink> subtype = subtypeClassFor(notable);

        final NotableLink link = repositoryService.instantiate(subtype);

        link.setNote(note);

        final Bookmark bookmark = bookmarkService.bookmarkFor(notable);
        link.setNotable(notable);
        link.setNotableStr(bookmark.toString());

        repositoryService.persistAndFlush(link);

        return link;
    }

    private Class<? extends NotableLink> subtypeClassFor(
            final Object classified) {
        Class<?> domainClass = classified.getClass();
        for (SubtypeProvider subtypeProvider : subtypeProviders) {
            Class<? extends NotableLink> subtype = subtypeProvider.subtypeFor(domainClass);
            if(subtype != null) {
                return subtype;
            }
        }
        throw new IllegalStateException(String.format(
                "No subtype of NotableLink was found for '%s'; implement the NotableLinkRepository.SubtypeProvider SPI",
                domainClass.getName()));
    }
    //endregion

    //endregion

    //region > updateLink
    @Programmatic
    public void updateLink(final Note note) {
        final NotableLink link = findByNote(note);
        sync(note, link);
    }
    //endregion

    //region > helpers (sync)

    /**
     * copy over details from the {@link Note#} to the {@link NotableLink} (derived propoerties to support querying).
     */
    void sync(final Note note, final NotableLink link) {
        if(link == null) {
            return;
        }
        link.setDate(note.getDate());
        link.setCalendarName(note.getCalendarName());
    }
    //endregion

    //region > SubtypeProvider SPI

    /**
     * SPI to be implemented (as a {@link DomainService}) for any domain object to which {@link NotableLink}s can be
     * attached.
     */
    public interface SubtypeProvider {
        /**
         * @return the subtype of {@link NotableLink} to use to hold the (type-safe) link of the domain object
         */
        @Programmatic
        Class<? extends NotableLink> subtypeFor(Class<?> domainObject);
    }
    /**
     * Convenience adapter to help implement the {@link SubtypeProvider} SPI; simply returns the class pair passed into constructor.
     */
    public abstract static class SubtypeProviderAbstract implements SubtypeProvider {
        private final Class<?> notableDomainType;
        private final Class<? extends NotableLink> notableLinkSubtype;

        protected SubtypeProviderAbstract(final Class<?> notableDomainType, final Class<? extends NotableLink> notableLinkSubtype) {
            this.notableDomainType = notableDomainType;
            this.notableLinkSubtype = notableLinkSubtype;
        }
        @Override
        public Class<? extends NotableLink> subtypeFor(final Class<?> candidateNotableDomainType) {
            return notableDomainType.isAssignableFrom(candidateNotableDomainType) ? notableLinkSubtype : null;
        }
    }

    //endregion

    //region > injected services

    @javax.inject.Inject
    RepositoryService repositoryService;

    @javax.inject.Inject
    TitleService titleService;

    @javax.inject.Inject
    ServiceRegistry2 serviceRegistry;

    @javax.inject.Inject
    BookmarkService bookmarkService;

    @Inject
    List<SubtypeProvider> subtypeProviders;
    //endregion

}


/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.deephacks.tools4j.cli;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;

/**
 * GNUishParser is responsible for parsing the command line arguments more or less
 * according to the GNU Argument Syntax:
 *
 * http://www.gnu.org/s/hello/manual/libc/Argument-Syntax.html.
 *
 * Inspiration from http://commons.apache.org/cli
 */
final class GNUishParser {
    private final Map<String, String> shortOpts = new HashMap<String, String>();
    private final Map<String, String> longOpts = new HashMap<String, String>();
    private final List<String> arguments = new ArrayList<String>();
    private String command;
    private static String VERBOSE_LONG_OPT = "verbose";
    private static String DEBUG_LONG_OPT = "debug";
    private static String HELP_LONG_OPT = "help";

    private GNUishParser() {
    }

    static GNUishParser parse(String[] terminalArgs) {
        final GNUishParser p = new GNUishParser();
        if (terminalArgs == null || terminalArgs.length == 0) {
            return p;
        }
        p.command = terminalArgs[0].trim();
        terminalArgs = Arrays.copyOfRange(terminalArgs, 1, terminalArgs.length);

        // we strip opts after parsing
        terminalArgs = p.parseOpts(terminalArgs);

        // arguments is what's left
        p.arguments.addAll(Arrays.asList(terminalArgs));
        return p;
    }

    /**
     * Parse the options for the command.
     *
     * @param args includes the options and arguments, command word have been stripped.
     * @return the remaining terminal args, if any
     */
    private String[] parseOpts(String[] args) {

        if (args == null || args.length == 0) {
            return new String[0];
        }
        final List<String> remainingArgs = new ArrayList<String>();
        final List<String> argsList = Arrays.asList(args);
        final ListIterator<String> argsIt = argsList.listIterator();

        while (argsIt.hasNext()) {
            String word = argsIt.next();
            if (word.startsWith("--")) {
                // long option --foo
                final String option = stripLeadingHyphens(word);
                if (VERBOSE_LONG_OPT.equals(option)) {
                    longOpts.put(option, "true");
                } else if (DEBUG_LONG_OPT.equals(option)) {
                    longOpts.put(option, "true");
                } else if (HELP_LONG_OPT.equals(option)) {
                    longOpts.put(option, "true");
                } else {
                    final String arg = parseOptionArg(option, argsIt);
                    longOpts.put(option, arg);
                }

            } else if (word.startsWith("-")) {
                String options = stripLeadingHyphens(word);

                // single short option -f
                if (options.length() == 1) {
                    // only slurp argument if option is argumented
                    final String arg = parseOptionArg(options, argsIt);
                    shortOpts.put(options, arg);
                    continue;
                }
                // multiple short options -fxy,
                // treat as non-argumented java.lang.Boolean variables, no slurp
                for (int i = 0; i < options.length(); i++) {
                    final String option = Character.toString(options.charAt(i));
                    shortOpts.put(option, "true");
                }
            } else {
                remainingArgs.add(word);
            }
        }
        return remainingArgs.toArray(new String[0]);
    }

    private String parseOptionArg(String option, ListIterator<String> argsIt) {
        if (!argsIt.hasNext()) {
            // no argument. assume boolean opt
            return "true";
        }

        String arg = argsIt.next();
        // the token following the option is a new option (not an argument)
        // digits following the hyphen are treated as arguments
        if (arg.startsWith("-") && arg.length() > 1 && !Character.isDigit(arg.charAt(1))) {
            // arg was the next opt, take one step back
            argsIt.previous();
            // assume argument for opt is a boolean
            arg = "true";
        }
        return arg;
    }

    private static String stripLeadingHyphens(String str) {
        if (str == null) {
            return null;
        }
        if (str.startsWith("--")) {
            return str.substring(2, str.length());
        } else if (str.startsWith("-")) {
            return str.substring(1, str.length());
        }
        return str;
    }

    String getCommand() {
        return command;
    }

    List<String> getArgs() {
        return arguments;
    }

    Map<String, String> getShortOpts() {
        return shortOpts;
    }

    String getShortOpt(String id) {
        return shortOpts.get(id);
    }

    Map<String, String> getLongOpts() {
        return longOpts;
    }

    String getLongOpt(String id) {
        return longOpts.get(id);
    }

    public static List<String> getReservedNonArgumentOptions() {
        return Arrays.asList(VERBOSE_LONG_OPT, DEBUG_LONG_OPT, HELP_LONG_OPT);
    }

    public boolean verbose() {
        if (getLongOpt(VERBOSE_LONG_OPT) != null) {
            return true;
        }
        return false;
    }

    public boolean debug() {
        if (getLongOpt(DEBUG_LONG_OPT) != null) {
            return true;
        }
        return false;
    }

    public boolean help() {
        if (getLongOpt(HELP_LONG_OPT) != null) {
            return true;
        }
        return false;
    }

}


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

package com.hi3project.vineyard.comm.stomp.gozirraws;

import java.util.Map;
import java.util.Iterator;

/**
 * A client that is connected directly to a server.  Messages sent via
 * this client do not go through a network interface, except when being
 * delivered to clients connected via the network... all messages to
 * other IntraVMClients are delivered entirely in memory.
 *
 * (c)2005 Sean Russell
 */
public class IntraVMClient extends Stomp implements Listener, Authenticatable {
  private Server _server;

  protected IntraVMClient( Server server ) {
    _server = server;
    _connected = true;
  }

  public boolean isClosed() { return false; }

  public Object token() {
    return "IntraVMClient";
  }

  /**
   * Transmit a message to clients and listeners.
   */
  public void transmit( Command c, Map h, String b ) {
    _server.receive( c, h, b, this );
  }

  public void disconnect( Map h ) {
    _server.receive( Command.DISCONNECT, null, null, this );
    _server = null;
  }

  public void message( Map headers, String body ) {
    receive( Command.MESSAGE, headers, body );
  }

  public void receipt( Map headers ) {
    receive( Command.RECEIPT, headers, null );
  }

  public void error( Map headers, String body ) {
    receive( Command.ERROR, headers, body );
  }
}


/*
 *
 *  Copyright 2015 incode.org
 *
 *
 *  Licensed under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 */
package org.incode.module.note.dom.impl.note;

import java.util.List;

import javax.inject.Inject;

import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

import org.joda.time.LocalDate;

import org.apache.isis.applib.annotation.DomainService;
import org.apache.isis.applib.annotation.NatureOfService;
import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.applib.query.QueryDefault;
import org.apache.isis.applib.services.repository.RepositoryService;

import org.incode.module.note.dom.impl.notablelink.NotableLink;
import org.incode.module.note.dom.impl.notablelink.NotableLinkRepository;

@DomainService(
        nature = NatureOfService.DOMAIN,
        repositoryFor = Note.class
)
public class NoteRepository {

    //region > findByNotable (programmatic)
    @Programmatic
    public List<Note> findByNotable(final Object notable) {
        final List<NotableLink> links = linkRepository.findByNotable(notable);
        return Lists.newArrayList(
                Iterables.transform(links, NotableLink.Functions.note()));
    }
    //endregion

    //region > findByNotableAndCalendarName (programmatic)
    @Programmatic
    public Note findByNotableAndCalendarName(
            final Object notable,
            final String calendarName) {
        final NotableLink link = linkRepository
                .findByNotableAndCalendarName(notable, calendarName);
        return NotableLink.Functions.note().apply(link);
    }
    //endregion

    //region > findInDateRange (programmatic)
    @Programmatic
    public List<Note> findInDateRange(
            final LocalDate startDate,
            final LocalDate endDate) {
        return repositoryService.allMatches(
                new QueryDefault<>(
                        Note.class,
                        "findInDateRange",
                        "startDate", startDate,
                        "endDate", endDate));
    }
    //endregion

    //region > findByNotableInDateRange (programmatic)
    @Programmatic
    public Iterable<Note> findByNotableInDateRange(
            final Object notable,
            final LocalDate startDate,
            final LocalDate endDate) {
        final List<NotableLink> link = linkRepository
                .findByNotableInDateRange(notable, startDate, endDate);
        return Iterables.transform(link, NotableLink.Functions.note());
    }
    //endregion

    //region > add (programmatic)

    @Programmatic
    public Note add(
            final Object notable,
            final String noteText,
            final LocalDate date,
            final String calendarName) {
        final Note note = repositoryService.instantiate(Note.class);
        note.setDate(date);
        note.setCalendarName(calendarName);
        note.setContent(noteText);
        repositoryService.persistAndFlush(note);

        final NotableLink link = notableLinkRepository.createLink(note, notable);
        // stored redundantly for querying...
        link.setCalendarName(calendarName);
        link.setDate(date);

        return note;
    }

    //endregion

    //region > remove (programmatic)
    @Programmatic
    public void remove(Note note) {
        final NotableLink link = linkRepository.findByNote(note);
        repositoryService.removeAndFlush(link);
        repositoryService.removeAndFlush(note);
    }
    //endregion

    //region > allNotes (programmatic)

    @Programmatic
    public List<Note> allNotes() {
        return repositoryService.allInstances(Note.class);
    }
    //endregion

    //region > injected
    @Inject
    NotableLinkRepository notableLinkRepository;
    @Inject
    NotableLinkRepository linkRepository;
    @Inject
    RepositoryService repositoryService;
    //endregion

}