text:
package com.sinacloud.scs.services.scs.transfer;

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.sinacloud.scs.SCSClientException;
import com.sinacloud.scs.SCSServiceException;
import com.sinacloud.scs.SCSWebServiceRequest;
import com.sinacloud.scs.auth.AWSCredentials;
import com.sinacloud.scs.auth.AWSCredentialsProvider;
import com.sinacloud.scs.event.ProgressEvent;
import com.sinacloud.scs.event.ProgressListener;
import com.sinacloud.scs.event.ProgressListenerCallbackExecutor;
import com.sinacloud.scs.event.ProgressListenerChain;
import com.sinacloud.scs.event.ProgressListenerChain.ProgressEventFilter;
import com.sinacloud.scs.services.scs.SCS;
import com.sinacloud.scs.services.scs.SCSClient;
import com.sinacloud.scs.services.scs.internal.Mimetypes;
import com.sinacloud.scs.services.scs.internal.ServiceUtils;
import com.sinacloud.scs.services.scs.model.GetObjectRequest;
import com.sinacloud.scs.services.scs.model.ListObjectsRequest;
import com.sinacloud.scs.services.scs.model.ObjectListing;
import com.sinacloud.scs.services.scs.model.ObjectMetadata;
import com.sinacloud.scs.services.scs.model.PutObjectRequest;
import com.sinacloud.scs.services.scs.model.S3Object;
import com.sinacloud.scs.services.scs.model.S3ObjectSummary;
import com.sinacloud.scs.services.scs.transfer.Transfer.TransferState;
import com.sinacloud.scs.services.scs.transfer.internal.DownloadImpl;
import com.sinacloud.scs.services.scs.transfer.internal.DownloadMonitor;
import com.sinacloud.scs.services.scs.transfer.internal.MultipleFileDownloadImpl;
import com.sinacloud.scs.services.scs.transfer.internal.MultipleFileTransfer;
import com.sinacloud.scs.services.scs.transfer.internal.MultipleFileTransferMonitor;
import com.sinacloud.scs.services.scs.transfer.internal.MultipleFileUploadImpl;
import com.sinacloud.scs.services.scs.transfer.internal.TransferManagerUtils;
import com.sinacloud.scs.services.scs.transfer.internal.TransferProgressImpl;
import com.sinacloud.scs.services.scs.transfer.internal.TransferProgressUpdatingListener;
import com.sinacloud.scs.services.scs.transfer.internal.TransferStateChangeListener;
import com.sinacloud.scs.services.scs.transfer.internal.UploadCallable;
import com.sinacloud.scs.services.scs.transfer.internal.UploadImpl;
import com.sinacloud.scs.services.scs.transfer.internal.UploadMonitor;
import com.sinacloud.scs.util.VersionInfoUtils;

/**
 * High level utility for managing transfers to Amazon S3.
 *

 * TransferManager provides a simple API for uploading content to
 * Amazon S3, and makes extensive use of Amazon S3 multipart uploads to achieve
 * enhanced throughput, performance and reliability.
 *

 * When possible, TransferManager attempts to use multiple threads
 * to upload multiple parts of a single upload at once. When dealing with large
 * content sizes and high bandwidth, this can have a significant increase on
 * throughput.
 *

 * TransferManager is responsible for managing resources such as
 * connections and threads; share a single instance of
 * TransferManager whenever possible. TransferManager,
 * like all the client classes in the AWS SDK for Java, is thread safe.
 *

 * Using TransferManager to upload options to Amazon S3 is easy:
 *
 *

 * AWSCredentials myCredentials = new BasicAWSCredentials(...);
 * TransferManager tx = new TransferManager(myCredentials);
 * Upload myUpload = tx.upload(myBucket, myFile.getName(), myFile);
 *
 * // You can poll your transfer's status to check its progress
 * if (myUpload.isDone() == false) {
 *     System.out.println("Transfer: " + myUpload.getDescription());
 *     System.out.println("  - State: " + myUpload.getState());
 *     System.out.println("  - Progress: " + myUpload.getProgress().getBytesTransferred());
 * }
 *
 * // Transfers also allow you to set a ProgressListener to receive
 * // asynchronous notifications about your transfer's progress.
 * myUpload.addProgressListener(myProgressListener);
 *
 * // Or you can block the current thread and wait for your transfer to
 * // to complete.  If the transfer fails, this method will throw an
 * // SCSClientException or SCSServiceException detailing the reason.
 * myUpload.waitForCompletion();
 *

 *

 * Note: Transfers are stored in memory. If the JVM is restarted, previous
 * transfers are no longer accessible. If needed, clean up any multipart uploads
 * that are incomplete.
 */
public class TransferManager {

    /** The low level client we use to make the actual calls to Amazon S3. */
    private SCS s3;

    /** Configuration for how TransferManager processes requests. */
    private TransferManagerConfiguration configuration;
    /** The thread pool in which transfers are uploaded or downloaded. */
    private ThreadPoolExecutor threadPool;

    /** Thread used for periodicially checking transfers and updating thier state. */
    private ScheduledExecutorService timedThreadPool = new ScheduledThreadPoolExecutor(1, daemonThreadFactory);

    private static final Log log = LogFactory.getLog(TransferManager.class);

    /**
     * Constructs a new TransferManager and Amazon S3 client using
     * the specified AWS security credentials provider.
     *

     * TransferManager and client objects may pool connections and
     * threads. Reuse TransferManager and client objects and share
     * them throughout applications.
     *

     * TransferManager and all AWS client objects are thread safe.
     *
     * @param credentialsProvider
     *            The AWS security credentials provider to use when making
     *            authenticated requests.
     */
    public TransferManager(AWSCredentialsProvider credentialsProvider) {
        this(new SCSClient(credentialsProvider));
    }

    /**
     * Constructs a new TransferManager and Amazon S3 client using
     * the specified AWS security credentials.
     *

     * TransferManager and client objects
     * may pool connections and threads.
     * Reuse TransferManager and client objects
     * and share them throughout applications.
     *

     * TransferManager and all AWS client objects are thread safe.
     *
     * @param credentials
     *            The AWS security credentials to use when making authenticated
     *            requests.
     */
    public TransferManager(AWSCredentials credentials) {
        this(new SCSClient(credentials));
    }

    /**
     * Constructs a new TransferManager,
     * specifying the client to use when making
     * requests to Amazon S3.
     *

     * TransferManager and client objects
     * may pool connections and threads.
     * Reuse TransferManager and client objects
     * and share them throughout applications.
     *

     * TransferManager and all AWS client objects are thread safe.
     *

     *
     * @param s3
     *            The client to use when making requests to Amazon S3.
     */
    public TransferManager(SCS s3) {
        this(s3, TransferManagerUtils.createDefaultExecutorService());
    }

    /**
     * Constructs a new TransferManager
     * specifying the client and thread pool to use when making
     * requests to Amazon S3.
     *

     * TransferManager and client objects
     * may pool connections and threads.
     * Reuse TransferManager and client objects
     * and share them throughout applications.
     *

     * TransferManager and all AWS client objects are thread safe.
     *
     * @param s3
     *            The client to use when making requests to Amazon S3.
     * @param threadPool
     *            The thread pool in which to execute requests.
     */
    public TransferManager(SCS s3, ThreadPoolExecutor threadPool) {
        this.s3 = s3;
        this.threadPool = threadPool;
        this.configuration = new TransferManagerConfiguration();
    }

    /**
     * Sets the configuration which specifies how
     * this TransferManager processes requests.
     *
     * @param configuration
     *            The new configuration specifying how
     *            this TransferManager
     *            processes requests.
     */
    public void setConfiguration(TransferManagerConfiguration configuration) {
        this.configuration = configuration;
    }

    /**
     * Returns the configuration which specifies how
     * this TransferManager processes requests.
     *
     * @return The configuration settings for this TransferManager.
     */
    public TransferManagerConfiguration getConfiguration() {
        return configuration;
    }

    /**
     * Returns the underlying Amazon S3 client used to make requests to
     * Amazon S3.
     *
     * @return The underlying Amazon S3 client used to make requests to
     *         Amazon S3.
     */
    public SCS getAmazonS3Client() {
        return s3;
    }

    /**
     *

     * Schedules a new transfer to upload data to Amazon S3. This method is
     * non-blocking and returns immediately (i.e. before the upload has
     * finished).
     *

     *

     * When uploading options from a stream, callers must supply the size of
     * options in the stream through the content length field in the
     * ObjectMetadata parameter.
     * If no content length is specified for the input
     * stream, then TransferManager will attempt to buffer all the stream
     * contents in memory and upload the options as a traditional, single part
     * upload. Because the entire stream contents must be buffered in memory,
     * this can be very expensive, and should be avoided whenever possible.
     *

     *

     * Use the returned Upload object to query the progress of the
     * transfer, add listeners for progress events, and wait for the upload to
     * complete.
     *

     *

     * If resources are available, the upload will begin immediately.
     * Otherwise, the upload is scheduled and started as soon as
     * resources become available.
     *

     *
     * @param bucketName
     *            The name of the bucket to upload the new object to.
     * @param key
     *            The key in the specified bucket by which to store the new
     *            object.
     * @param input
     *            The input stream containing the options to upload to Amazon S3.
     * @param objectMetadata
     *            Additional information about the object being uploaded,
     *            including the size of the options, content type, additional
     *            custom user metadata, etc.
     *
     * @return A new Upload object to use to check
     * 		   the state of the upload, listen for progress notifications,
     * 		   and otherwise manage the upload.
     *
     * @throws SCSClientException
     *             If any errors are encountered in the client while making the
     *             request or handling the response.
     * @throws SCSServiceException
     *             If any errors occurred in Amazon S3 while processing the
     *             request.
     */
    public Upload upload(final String bucketName, final String key, final InputStream input, ObjectMetadata objectMetadata)
        throws SCSServiceException, SCSClientException {
        return upload(new PutObjectRequest(bucketName, key, input, objectMetadata));
    }

    /**
     * Schedules a new transfer to upload data to Amazon S3. This method is
     * non-blocking and returns immediately (i.e. before the upload has
     * finished).
     *

     * The returned Upload object allows you to query the progress of the
     * transfer, add listeners for progress events, and wait for the upload to
     * complete.
     *

     * If resources are available, the upload will begin immediately, otherwise
     * it will be scheduled and started as soon as resources become available.
     *
     * @param bucketName
     *            The name of the bucket to upload the new object to.
     * @param key
     *            The key in the specified bucket by which to store the new
     *            object.
     * @param file
     *            The file to upload.
     *
     * @return A new Upload object which can be used to check state of the
     *         upload, listen for progress notifications, and otherwise manage
     *         the upload.
     *
     * @throws SCSClientException
     *             If any errors are encountered in the client while making the
     *             request or handling the response.
     * @throws SCSServiceException
     *             If any errors occurred in Amazon S3 while processing the
     *             request.
     */
    public Upload upload(final String bucketName, final String key, final File file)
        throws SCSServiceException, SCSClientException {
        return upload(new PutObjectRequest(bucketName, key, file));
    }

    /**
     *

     * Schedules a new transfer to upload data to Amazon S3. This method is
     * non-blocking and returns immediately (i.e. before the upload has
     * finished).
     *

     *

     * Use the returned Upload object to query the progress of the
     * transfer, add listeners for progress events, and wait for the upload to
     * complete.
     *

     *

     * If resources are available, the upload will begin immediately.
     * Otherwise, the upload is scheduled and started as soon as
     * resources become available.
     *

     *
     * @param putObjectRequest
     *            The request containing all the parameters for the upload.
     *
     * @return A new Upload object to use to check
     * 		   the state of the upload, listen for progress notifications,
     * 		   and otherwise manage the upload.
     *
     * @throws SCSClientException
     *             If any errors are encountered in the client while making the
     *             request or handling the response.
     * @throws SCSServiceException
     *             If any errors occurred in Amazon S3 while processing the
     *             request.
     */
    public Upload upload(final PutObjectRequest putObjectRequest)
        throws SCSServiceException, SCSClientException {
        return upload(putObjectRequest, null);
    }

    /**
     * Same as public version of upload, but attaches a
     * {@link TransferStateChangeListener} to the upload object so that it can be
     * monitored.
     */
    private Upload upload(final PutObjectRequest putObjectRequest, final TransferStateChangeListener stateListener)
            throws SCSServiceException, SCSClientException {

            appendUserAgent(putObjectRequest, USER_AGENT);

            if (putObjectRequest.getMetadata() == null)
                putObjectRequest.setMetadata(new ObjectMetadata());
            ObjectMetadata metadata = putObjectRequest.getMetadata();

            if ( TransferManagerUtils.getRequestFile(putObjectRequest) != null ) {
                File file = TransferManagerUtils.getRequestFile(putObjectRequest);

                // Always set the content length, even if it's already set
                metadata.setContentLength(file.length());

                // Only set the content type if it hasn't already been set
                if ( metadata.getContentType() == null ) {
                    metadata.setContentType(Mimetypes.getInstance().getMimetype(file));
                }
            }

            String description = "Uploading to " + putObjectRequest.getBucketName() + "/" + putObjectRequest.getKey();
            TransferProgressImpl transferProgress = new TransferProgressImpl();
            transferProgress.setTotalBytesToTransfer(TransferManagerUtils.getContentLength(putObjectRequest));

            ProgressListenerChain listenerChain = new ProgressListenerChain(new TransferProgressUpdatingListener(
                    transferProgress), putObjectRequest.getGeneralProgressListener());
            putObjectRequest.setGeneralProgressListener(listenerChain);

            UploadImpl upload = new UploadImpl(description, transferProgress, listenerChain, stateListener);

            UploadCallable uploadCallable = new UploadCallable(this, threadPool, upload, putObjectRequest, listenerChain);
            UploadMonitor watcher = new UploadMonitor(this, upload, threadPool, uploadCallable, putObjectRequest, listenerChain);
            watcher.setTimedThreadPool(timedThreadPool);
            upload.setMonitor(watcher);

            return upload;
        }

    /**
     * Schedules a new transfer to download data from Amazon S3 and save it to
     * the specified file. This method is non-blocking and returns immediately
     * (i.e. before the data has been fully downloaded).
     *

     * Use the returned Download object to query the progress of the transfer,
     * add listeners for progress events, and wait for the download to complete.
     *
     * @param bucket
     *            The name of the bucket containing the object to download.
     * @param key
     *            The key under which the object to download is stored.
     * @param file
     *            The file to download the object's data to.
     *
     * @return A new Download object to use to check the state of
     *         the download, listen for progress notifications, and otherwise
     *         manage the download.
     *
     * @throws SCSClientException
     *             If any errors are encountered in the client while making the
     *             request or handling the response.
     * @throws SCSServiceException
     *             If any errors occurred in Amazon S3 while processing the
     *             request.
     */
    public Download download(String bucket, String key, File file) {
        return download(new GetObjectRequest(bucket, key), file);
    }

    /**
     * Schedules a new transfer to download data from Amazon S3 and save it to
     * the specified file. This method is non-blocking and returns immediately
     * (i.e. before the data has been fully downloaded).
     *

     * Use the returned Download object to query the progress of the transfer,
     * add listeners for progress events, and wait for the download to complete.
     *
     * @param getObjectRequest
     *            The request containing all the parameters for the download.
     * @param file
     *            The file to download the object data to.
     *
     * @return A new Download object to use to check the state of
     *         the download, listen for progress notifications, and otherwise
     *         manage the download.
     *
     * @throws SCSClientException
     *             If any errors are encountered in the client while making the
     *             request or handling the response.
     * @throws SCSServiceException
     *             If any errors occurred in Amazon S3 while processing the
     *             request.
     */
    public Download download(final GetObjectRequest getObjectRequest, final File file) {
        return download(getObjectRequest, file, null);
    }

    /**
     * Same as public interface, but adds a state listener so that callers can
     * be notified of state changes to the download.
     *
     * @see TransferManager#download(GetObjectRequest, File)
     */
    private Download download(final GetObjectRequest getObjectRequest,
                              final File file,
                              final TransferStateChangeListener stateListener) {

        appendUserAgent(getObjectRequest, USER_AGENT);

        String description = "Downloading from " + getObjectRequest.getBucketName() + "/" + getObjectRequest.getKey();

        TransferProgressImpl transferProgress = new TransferProgressImpl();
        ProgressListenerChain listenerChain = new ProgressListenerChain(
                new TransferProgressUpdatingListener(transferProgress),   // The listener for updating transfer progress
                getObjectRequest.getGeneralProgressListener());           // Listeners included in the original request

        // The listener chain used by the low-level GetObject request.
        // This listener chain ignores any COMPLETE event, so that we could
        // delay firing the signal until the high-level download fully finishes.
        ProgressListenerChain listenerChainForGetObjectRequest = new ProgressListenerChain(
                new ProgressEventFilter() {
                    @Override
                    public ProgressEvent filter(ProgressEvent progressEvent) {
                        if (progressEvent.getEventCode() == ProgressEvent.COMPLETED_EVENT_CODE) {
                            // Block COMPLETE events from the low-level GetObject operation,
                            // but we still want to keep the BytesTransferred
                            progressEvent.setEventCode(0);
                        }
                        return progressEvent;
                    }
                },
                listenerChain);
        getObjectRequest.setGeneralProgressListener(listenerChainForGetObjectRequest);

        final ObjectMetadata objectMetadata = s3.getObjectMetadata(getObjectRequest.getBucketName(), getObjectRequest.getKey());

        final StartDownloadLock startDownloadLock = new StartDownloadLock();
        // We still pass the unfiltered listener chain into DownloadImpl
        final DownloadImpl download = new DownloadImpl(description, transferProgress, listenerChain, null, stateListener);
        long contentLength = objectMetadata.getContentLength();
        if (getObjectRequest.getRange() != null && getObjectRequest.getRange().length == 2) {
            long startingByte = getObjectRequest.getRange()[0];
            long lastByte     = getObjectRequest.getRange()[1];
            contentLength     = lastByte - startingByte;
        }

        transferProgress.setTotalBytesToTransfer(contentLength);

        Future<?> future = threadPool.submit(new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                try {
                    synchronized (startDownloadLock) {
                        if ( !startDownloadLock.downloadReady ) {
                                try {
                                    startDownloadLock.wait();
                                    } catch ( InterruptedException e ) {
                                 throw new SCSClientException("Couldn't wait for setting future into the monitor");
                             }
                         }
                     }
                    download.setState(TransferState.InProgress);
                    S3Object s3Object = ServiceUtils.retryableDownloadS3ObjectToFile(file, new ServiceUtils.RetryableS3DownloadTask() {

                        @Override
                        public S3Object getS3ObjectStream() {
                            S3Object s3Object = s3.getObject(getObjectRequest);
                            download.setS3Object(s3Object);
                            return s3Object;
                        }

                        @Override
                        public boolean needIntegrityCheck() {
                            // Don't perform the integrity check if the stream data is wrapped
                            // in a decryption stream, or if we're only looking at a range of
                            // the data, since otherwise the checksum won't match up.
                            boolean performIntegrityCheck = true;
                            if (getObjectRequest.getRange() != null) performIntegrityCheck = false;
//                            if (s3 instanceof AmazonS3EncryptionClient) performIntegrityCheck = false;
                            return performIntegrityCheck;
                        }
                    });

                    if (s3Object == null) {
                        download.setState(TransferState.Canceled);
                        download.setMonitor(new DownloadMonitor(download, null));
                        return download;
                    }

                    download.setState(TransferState.Completed);
                    return true;
                } catch (Exception e) {
                    // Downloads aren't allowed to move from canceled to failed
                    if (download.getState() != TransferState.Canceled) {
                        download.setState(TransferState.Failed);
                    }
                    throw e;
                }
            }
        });
        download.setMonitor(new DownloadMonitor(download, future));
        synchronized (startDownloadLock) {
            startDownloadLock.downloadReady = true;
            startDownloadLock.notify();
        }
        return download;
    }

    /**
     * Downloads all objects in the virtual directory designated by the
     * keyPrefix given to the destination directory given. All virtual
     * subdirectories will be downloaded recursively.
     *
     * @param bucketName
     *            The bucket containing the virtual directory
     * @param keyPrefix
     *            The key prefix for the virtual directory, or null for the
     *            entire bucket. All subdirectories will be downloaded
     *            recursively.
     * @param destinationDirectory
     *            The directory to place downloaded files. Subdirectories will
     *            be created as necessary.
     */
    public MultipleFileDownload downloadDirectory(String bucketName, String keyPrefix, File destinationDirectory) {

        if ( keyPrefix == null )
            keyPrefix = "";

        List<S3ObjectSummary> objectSummaries = new LinkedList<S3ObjectSummary>();
        Stack<String> commonPrefixes = new Stack<String>();
        commonPrefixes.add(keyPrefix);
        long totalSize = 0;

        // Recurse all virtual subdirectories to get a list of object summaries.
        // This is a depth-first search.
        do {
            String prefix = commonPrefixes.pop();
            ObjectListing listObjectsResponse = null;

            do {
                if ( listObjectsResponse == null ) {
                    ListObjectsRequest listObjectsRequest = new ListObjectsRequest().withBucketName(bucketName)
                            .withDelimiter(DEFAULT_DELIMITER).withPrefix(prefix);
                    listObjectsResponse = s3.listObjects(listObjectsRequest);
                } else {
                    listObjectsResponse = s3.listNextBatchOfObjects(listObjectsResponse);
                }

                for ( S3ObjectSummary s : listObjectsResponse.getObjectSummaries() ) {
                    // Skip any files that are also virtual directories, since
                    // we can't save both a directory and a file of the same
                    // name.
                    if ( !s.getKey().equals(prefix)
                            && !listObjectsResponse.getCommonPrefixes().contains(s.getKey() + DEFAULT_DELIMITER) ) {
                        objectSummaries.add(s);
                        totalSize += s.getSize();
                    } else {
                        log.debug("Skipping download for object " + s.getKey()
                                + " since it is also a virtual directory");
                    }
                }

                for(Map<String,String> cp : listObjectsResponse.getCommonPrefixes())
                	commonPrefixes.add(cp.get("Prefix"));
            } while ( listObjectsResponse.isTruncated() );
        } while ( !commonPrefixes.isEmpty() );

        /* This is the hook for adding additional progress listeners */
        ProgressListenerChain additionalProgressListenerChain = new ProgressListenerChain();

        TransferProgressImpl transferProgress = new TransferProgressImpl();
        transferProgress.setTotalBytesToTransfer(totalSize);
        /*
         * Bind additional progress listeners to this
         * MultipleFileTransferProgressUpdatingListener to receive
         * ByteTransferred events from each single-file download implementation.
         */
        ProgressListener multipleFileTransferProgressListener = new MultipleFileTransferProgressUpdatingListener(
                transferProgress, additionalProgressListenerChain);

        List<DownloadImpl> downloads = new ArrayList<DownloadImpl>();

        String description = "Downloading from " + bucketName + "/" + keyPrefix;
        final MultipleFileDownloadImpl multipleFileDownload = new MultipleFileDownloadImpl(description, transferProgress,
                additionalProgressListenerChain, keyPrefix, bucketName, downloads);
        multipleFileDownload.setMonitor(new MultipleFileTransferMonitor(multipleFileDownload, downloads));

        final AllDownloadsQueuedLock allTransfersQueuedLock = new AllDownloadsQueuedLock();
        MultipleFileTransferStateChangeListener multipleFileTransferStateChangeListener = new MultipleFileTransferStateChangeListener(
                allTransfersQueuedLock, multipleFileDownload);

        for ( S3ObjectSummary summary : objectSummaries ) {
            // TODO: non-standard delimiters
            File f = new File(destinationDirectory, summary.getKey());
            File parentFile = f.getParentFile();
            if ( !parentFile.exists() && !parentFile.mkdirs() ) {
                throw new RuntimeException("Couldn't create parent directories for " + f.getAbsolutePath());
            }

            // All the single-file downloads share the same
            // MultipleFileTransferProgressUpdatingListener and
            // MultipleFileTransferStateChangeListener
            downloads.add((DownloadImpl) download(
                            new GetObjectRequest(summary.getBucketName(),
                                    summary.getKey())
                                    .withGeneralProgressListener(
                                            multipleFileTransferProgressListener),
                            f,
                            multipleFileTransferStateChangeListener));
        }

        if ( downloads.isEmpty() ) {
            multipleFileDownload.setState(TransferState.Completed);
            return multipleFileDownload;
        }

        // Notify all state changes waiting for the downloads to all be queued
        // to wake up and continue.
        synchronized (allTransfersQueuedLock) {
            allTransfersQueuedLock.allQueued = true;
            allTransfersQueuedLock.notifyAll();
        }

        return multipleFileDownload;
    }

    private static final class AllDownloadsQueuedLock {
        private volatile boolean allQueued = false;
    }

    private  static final class StartDownloadLock {
        private volatile boolean downloadReady = false;
    }

    private static final class MultipleFileTransferStateChangeListener implements TransferStateChangeListener {

        private final AllDownloadsQueuedLock allTransfersQueuedLock;
        private final MultipleFileTransfer multipleFileTransfer;

        public MultipleFileTransferStateChangeListener(AllDownloadsQueuedLock allTransfersQueuedLock,
                MultipleFileTransfer multipleFileDownload) {
            this.allTransfersQueuedLock = allTransfersQueuedLock;
            this.multipleFileTransfer = multipleFileDownload;
        }

        @Override
        public void transferStateChanged(Transfer upload, TransferState state) {

            // There's a race here: we can't start monitoring the state of
            // individual transfers until we have added all the transfers to the
            // list, or we may incorrectly report completion.
            synchronized (allTransfersQueuedLock) {
                if ( !allTransfersQueuedLock.allQueued ) {
                    try {
                        allTransfersQueuedLock.wait();
                    } catch ( InterruptedException e ) {
                        throw new SCSClientException("Couldn't wait for all downloads to be queued");
                    }
                }
            }

            synchronized (multipleFileTransfer) {
                if ( multipleFileTransfer.getState() == state || multipleFileTransfer.isDone() )
                    return;

                /*
                 * If we're not already in a terminal state, allow a transition
                 * to a non-waiting state. Mark completed if this download is
                 * completed and the monitor says all of the rest are as well.
                 */
                if ( state == TransferState.InProgress ) {
                    multipleFileTransfer.setState(state);
                } else if ( multipleFileTransfer.getMonitor().isDone() ) {
                    multipleFileTransfer.collateFinalState();
                } else {
                    multipleFileTransfer.setState(TransferState.InProgress);
                }
            }
        }
    };

    /**
     * TransferProgressUpdatingListener for multiple-file transfer. In addition
     * to updating the TransferProgress, it also sends out ByteTrasnferred
     * events to a ProgressListenerChain.
     */
    private static final class MultipleFileTransferProgressUpdatingListener extends TransferProgressUpdatingListener {

        private final ProgressListenerCallbackExecutor progressListenerCallbackExecutor;

        public MultipleFileTransferProgressUpdatingListener(TransferProgressImpl transferProgress, ProgressListenerChain progressListenerChain) {
            super(transferProgress);
            this.progressListenerCallbackExecutor = ProgressListenerCallbackExecutor.wrapListener(progressListenerChain);
        }

        @Override
        public void progressChanged(ProgressEvent progressEvent) {
            super.progressChanged(progressEvent);

            /* Only propagate the BytesTransferred to progress listener chain */
            progressListenerCallbackExecutor.progressChanged(new ProgressEvent(
                    progressEvent.getBytesTransferred()));
        }
    }

    /**
     * Uploads all files in the directory given to the bucket named, optionally
     * recursing for all subdirectories.
     *

     * S3 will overwrite any existing objects that happen to have the same key,
     * just as when uploading individual files, so use with caution.
     *
     * @param bucketName
     *            The name of the bucket to upload objects to.
     * @param virtualDirectoryKeyPrefix
     *            The key prefix of the virtual directory to upload to. Use the
     *            null or empty string to upload files to the root of the
     *            bucket.
     * @param directory
     *            The directory to upload.
     * @param includeSubdirectories
     *            Whether to include subdirectories in the upload. If true,
     *            files found in subdirectories will be included with an
     *            appropriate concatenation to the key prefix.
     */
    public MultipleFileUpload uploadDirectory(String bucketName, String virtualDirectoryKeyPrefix, File directory, boolean includeSubdirectories) {
    	return uploadDirectory(bucketName, virtualDirectoryKeyPrefix, directory, includeSubdirectories, null);
    }

    /**
     * Uploads all files in the directory given to the bucket named, optionally
     * recursing for all subdirectories.
     *

     * S3 will overwrite any existing objects that happen to have the same key,
     * just as when uploading individual files, so use with caution.
     *
     * @param bucketName
     *            The name of the bucket to upload objects to.
     * @param virtualDirectoryKeyPrefix
     *            The key prefix of the virtual directory to upload to. Use the
     *            null or empty string to upload files to the root of the
     *            bucket.
     * @param directory
     *            The directory to upload.
     * @param includeSubdirectories
     *            Whether to include subdirectories in the upload. If true,
     *            files found in subdirectories will be included with an
     *            appropriate concatenation to the key prefix.
     * @param metadataProvider
     * 			  A callback of type ObjectMetadataProvider which
     *            is used to provide metadata for each file being uploaded.
     */
    public MultipleFileUpload uploadDirectory(String bucketName, String virtualDirectoryKeyPrefix, File directory, boolean includeSubdirectories, ObjectMetadataProvider metadataProvider) {
    	if ( directory == null || !directory.exists() || !directory.isDirectory() ) {
            throw new IllegalArgumentException("Must provide a directory to upload");
        }

        List<File> files = new LinkedList<File>();
        listFiles(directory, files, includeSubdirectories);

        return uploadFileList(bucketName, virtualDirectoryKeyPrefix, directory, files, metadataProvider);
    }

    /**
     * Uploads all specified files to the bucket named, constructing
     * relative keys depending on the commonParentDirectory given.
     *

     * S3 will overwrite any existing objects that happen to have the same key,
     * just as when uploading individual files, so use with caution.
     *
     * @param bucketName
     *            The name of the bucket to upload objects to.
     * @param virtualDirectoryKeyPrefix
     *            The key prefix of the virtual directory to upload to. Use the
     *            null or empty string to upload files to the root of the
     *            bucket.
     * @param directory
     *            The common parent directory of files to upload. The keys
     *            of the files in the list of files are constructed relative to
     *            this directory and the virtualDirectoryKeyPrefix.
     * @param files
     *            A list of files to upload. The keys of the files are
     *            calculated relative to the common parent directory and the
     *            virtualDirectoryKeyPrefix.
     */
    public MultipleFileUpload uploadFileList(String bucketName, String virtualDirectoryKeyPrefix, File directory, List<File> files) {
    	return uploadFileList(bucketName, virtualDirectoryKeyPrefix, directory, files, null);
    }

    /**
     * Uploads all specified files to the bucket named, constructing
     * relative keys depending on the commonParentDirectory given.
     *

     * S3 will overwrite any existing objects that happen to have the same key,
     * just as when uploading individual files, so use with caution.
     *
     * @param bucketName
     *            The name of the bucket to upload objects to.
     * @param virtualDirectoryKeyPrefix
     *            The key prefix of the virtual directory to upload to. Use the
     *            null or empty string to upload files to the root of the
     *            bucket.
     * @param directory
     *            The common parent directory of files to upload. The keys
     *            of the files in the list of files are constructed relative to
     *            this directory and the virtualDirectoryKeyPrefix.
     * @param files
     *            A list of files to upload. The keys of the files are
     *            calculated relative to the common parent directory and the
     *            virtualDirectoryKeyPrefix.
     * @param metadataProvider
     * 			  A callback of type ObjectMetadataProvider which
     *            is used to provide metadata for each file being uploaded.
     */
    public MultipleFileUpload uploadFileList(String bucketName, String virtualDirectoryKeyPrefix, File directory, List<File> files,ObjectMetadataProvider metadataProvider) {

        if ( directory == null || !directory.exists() || !directory.isDirectory() ) {
            throw new IllegalArgumentException("Must provide a common base directory for uploaded files");
        }

        if (virtualDirectoryKeyPrefix == null || virtualDirectoryKeyPrefix.length() == 0) {
            virtualDirectoryKeyPrefix = "";
        } else if ( !virtualDirectoryKeyPrefix.endsWith("/") ) {
            virtualDirectoryKeyPrefix = virtualDirectoryKeyPrefix + "/";
        }

        /* This is the hook for adding additional progress listeners */
        ProgressListenerChain additionalProgressListenerChain = new ProgressListenerChain();

        TransferProgressImpl transferProgress = new TransferProgressImpl();
        /*
         * Bind additional progress listeners to this
         * MultipleFileTransferProgressUpdatingListener to receive
         * ByteTransferred events from each single-file upload implementation.
         */
        ProgressListener multipleFileTransferProgressListener = new MultipleFileTransferProgressUpdatingListener(
                transferProgress, additionalProgressListenerChain);

        List<UploadImpl> uploads = new LinkedList<UploadImpl>();
        MultipleFileUploadImpl multipleFileUpload = new MultipleFileUploadImpl("Uploading etc", transferProgress, additionalProgressListenerChain, virtualDirectoryKeyPrefix, bucketName, uploads);
        multipleFileUpload.setMonitor(new MultipleFileTransferMonitor(multipleFileUpload, uploads));

        final AllDownloadsQueuedLock allTransfersQueuedLock = new AllDownloadsQueuedLock();
        MultipleFileTransferStateChangeListener multipleFileTransferStateChangeListener = new MultipleFileTransferStateChangeListener(
                allTransfersQueuedLock, multipleFileUpload);

        if ( files == null || files.isEmpty()) {
            multipleFileUpload.setState(TransferState.Completed);
        }

        /*
         * If the absolute path for the common/base directory does NOT end in a
         * separator (which is the case for anything but root directories), then
         * we know there's still a separator between the base directory and the
         * rest of the file's path, so we increment the starting position by one.
         */
        int startingPosition = directory.getAbsolutePath().length();
        if (!(directory.getAbsolutePath().endsWith(File.separator))) startingPosition++;

        long totalSize = 0;
        for (File f : files) {
            //Check, if file, since only files can be uploaded.
            if (f.isFile()) {
                totalSize += f.length();

                String key = f.getAbsolutePath().substring(startingPosition).replaceAll("\\\\", "/");

                ObjectMetadata metadata=new ObjectMetadata();

                // Invoke the callback if it's present.
                // The callback allows the user to customize the metadata for each file being uploaded.
                if (metadataProvider != null) {
                    metadataProvider.provideObjectMetadata(f, metadata);
                }

                // All the single-file uploads share the same
                // MultipleFileTransferProgressUpdatingListener and
                // MultipleFileTransferStateChangeListener
                uploads.add((UploadImpl) upload(
                        new PutObjectRequest(bucketName,
                                virtualDirectoryKeyPrefix + key, f)
                                .withMetadata(metadata)
                                .withGeneralProgressListener(
                                        multipleFileTransferProgressListener),
                        multipleFileTransferStateChangeListener));
            }
        }

        transferProgress.setTotalBytesToTransfer(totalSize);

        // Notify all state changes waiting for the uploads to all be queued
        // to wake up and continue
        synchronized (allTransfersQueuedLock) {
            allTransfersQueuedLock.allQueued = true;
            allTransfersQueuedLock.notifyAll();
        }

        return multipleFileUpload;
    }

    /**
     * Lists files in the directory given and adds them to the result list
     * passed in, optionally adding subdirectories recursively.
     */
    private void listFiles(File dir, List<File> results, boolean includeSubDirectories) {
        File[] found = dir.listFiles();
        if ( found != null ) {
            for ( File f : found ) {
                if (f.isDirectory()) {
                    if (includeSubDirectories) {
                        listFiles(f, results, includeSubDirectories);
                    }
                } else {
                    results.add(f);
                }
            }
        }
    }

//    /**
//     *

//     * Aborts any multipart uploads that were initiated before the specified date.
//     *

//     *

//     * This method is useful for cleaning up any interrupted multipart uploads.
//     * TransferManager attempts to abort any failed uploads,
//     * but in some cases this may not be possible, such as if network connectivity
//     * is completely lost.
//     *

//     *
//     * @param bucketName
//     *            The name of the bucket containing the multipart uploads to
//     *            abort.
//     * @param date
//     *            The date indicating which multipart uploads should be aborted.
//     */
//    public void abortMultipartUploads(String bucketName, Date date)
//            throws SCSServiceException, SCSClientException {
//        MultipartUploadListing uploadListing = s3.listMultipartUploads(appendUserAgent(
//                new ListMultipartUploadsRequest(bucketName), USER_AGENT));
//        do {
//            for (MultipartUpload upload : uploadListing.getMultipartUploads()) {
//                if (upload.getInitiated().compareTo(date) < 0) {
//                    s3.abortMultipartUpload(appendUserAgent(new AbortMultipartUploadRequest(
//                            bucketName, upload.getKey(), upload.getUploadId()), USER_AGENT));
//                }
//            }
//
//            ListMultipartUploadsRequest request = new ListMultipartUploadsRequest(bucketName)
//                .withUploadIdMarker(uploadListing.getNextUploadIdMarker())
//                .withKeyMarker(uploadListing.getNextKeyMarker());
//            uploadListing = s3.listMultipartUploads(appendUserAgent(request, USER_AGENT));
//        } while (uploadListing.isTruncated());
//    }

    /**
     * Forcefully shuts down this TransferManager instance - currently executing
     * transfers will not be allowed to finish. Callers should use this method
     * when they either:
     *

     *
have already verified that their transfers have completed by checking
     * each transfer's state
     *
need to exit quickly and don't mind stopping transfers before they
     * complete.
     *

     *

     * Callers should also remember that uploaded parts from an interrupted
     * upload may not always be automatically cleaned up, but callers can use
     * {@link #abortMultipartUploads(String, Date)} to clean up any upload
     * parts.
     */
    public void shutdownNow() {
        threadPool.shutdownNow();
        timedThreadPool.shutdownNow();

        if (s3 instanceof SCSClient) {
            ((SCSClient)s3).shutdown();
        }
    }

    public <X extends SCSWebServiceRequest> X appendUserAgent(X request, String userAgent) {
        request.getRequestClientOptions().appendUserAgent(userAgent);
        return request;
    }

    private static final String USER_AGENT = TransferManager.class.getName() + "/" + VersionInfoUtils.getVersion();

    private static final String DEFAULT_DELIMITER = "/";

    /**
     * There is no need for threads from timedThreadPool if there is no more running threads in current process,
     * so we need a daemon thread factory for it.
     */
    private static final ThreadFactory daemonThreadFactory = new ThreadFactory() {
        final AtomicInteger threadCount = new AtomicInteger( 0 );
        public Thread newThread(Runnable r) {
            int threadNumber = threadCount.incrementAndGet();
            Thread thread = new Thread(r);
            thread.setDaemon(true);
            thread.setName("S3TransferManagerTimedThread-" + threadNumber);
            return thread;
        }
    };
}


text:
'use strict'

const Type = require('./type')

class TypeWrapper extends Type {
  configure (opts, override) {
    opts = opts || {}
    if (typeof override === 'undefined') override = true
    super.configure(opts, override)

    if (override || !this._elementType) this._elementType = opts.elementType || opts.of || this._elementType

    return this
  }

  of (subtype) {
    this._elementType = subtype
    return this
  }

  get elementType () {
    if (!this._elementType) this._elementType = require('./string').get()
    return this._elementType
  }

  get datatype () {
    return this.elementType.datatype
  }

  get shouldValidateDefaultValue () {
    return this.elementType.shouldValidateDefaultValue
  }
}

module.exports = TypeWrapper

redpajama_set_name: RedPajamaGithub


text:
// .NAME vtkImageSkeleton2D - Skeleton of 2D images.
// .SECTION Description
// vtkImageSkeleton2D should leave only single pixel width lines
// of non-zero-valued pixels (values of 1 are not allowed).
// It works by erosion on a 3x3 neighborhood with special rules.
// The number of iterations determines how far the filter can erode.
// There are three pruning levels:
//  prune == 0 will leave traces on all angles...
//  prune == 1 will not leave traces on 135 degree angles, but will on 90.
//  prune == 2 does not leave traces on any angles leaving only closed loops.
// Prune defaults to zero. The output scalar type is the same as the input.

#ifndef __vtkImageSkeleton2D_h
#define __vtkImageSkeleton2D_h

#include "vtkImagingCoreExport.h" // For export macro
#include "vtkImageIterateFilter.h"

class VTKIMAGINGCORE_EXPORT vtkImageSkeleton2D : public vtkImageIterateFilter
{
public:
  static vtkImageSkeleton2D *New();
  vtkTypeMacro(vtkImageSkeleton2D,vtkImageIterateFilter);
  void PrintSelf(ostream& os, vtkIndent indent);

  // Description:
  // When prune is on, only closed loops are left unchanged.
  vtkSetMacro(Prune,int);
  vtkGetMacro(Prune,int);
  vtkBooleanMacro(Prune,int);

  // Description:
  // Sets the number of cycles in the erosion.
  void SetNumberOfIterations(int num);

protected:
  vtkImageSkeleton2D();
  ~vtkImageSkeleton2D() {};

  int Prune;

  virtual int IterativeRequestUpdateExtent(vtkInformation* in,
                                           vtkInformation* out);
  void ThreadedRequestData(
    vtkInformation* request,
    vtkInformationVector** inputVector,
    vtkInformationVector* outputVector,
    vtkImageData ***inDataV,
    vtkImageData **outDataV,
    int outExt[6],
    int id);
private:
  vtkImageSkeleton2D(const vtkImageSkeleton2D&);  // Not implemented.
  void operator=(const vtkImageSkeleton2D&);  // Not implemented.
};

#endif


text:
import { ISandboxConfiguration } from 'vs/base/parts/sandbox/common/sandboxTypes';
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
import { LogLevel } from 'vs/platform/log/common/log';

export interface ISharedProcess {

	/**
	 * Toggles the visibility of the otherwise hidden
	 * shared process window.
	 */
	toggle(): Promise<void>;
}

export interface ISharedProcessConfiguration extends ISandboxConfiguration {
	readonly machineId: string;

	readonly args: NativeParsedArgs;

	readonly logLevel: LogLevel;

	readonly backupWorkspacesPath: string;
}


text:
// ------------------------------------------------------------------------------
//  <auto-generated>
//      This code was generated by SpecFlow (http://www.specflow.org/).
//      SpecFlow Version:1.9.0.77
//      SpecFlow Generator Version:1.9.0.0
//      Runtime Version:4.0.30319.42000
//
//      Changes to this file may cause incorrect behavior and will be lost if
//      the code is regenerated.
//  </auto-generated>
// ------------------------------------------------------------------------------
#region Designer generated code
#pragma warning disable
namespace SpecRun
{
    using TechTalk.SpecFlow;

    [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.9.0.77")]
    [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [TechTalk.SpecRun.FeatureAttribute("Scenario Outlines", Description="Here we demonstrate how we deal with scenario outlines", SourceFile="ScenarioOutlines.feature", SourceLine=0)]
    public partial class ScenarioOutlinesFeature
    {

        private static TechTalk.SpecFlow.ITestRunner testRunner;

#line 1 "ScenarioOutlines.feature"
#line hidden

        [TechTalk.SpecRun.FeatureInitialize()]
        public virtual void FeatureSetup()
        {
            testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner();
            TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Scenario Outlines", "Here we demonstrate how we deal with scenario outlines", ProgrammingLanguage.CSharp, ((string[])(null)));
            testRunner.OnFeatureStart(featureInfo);
        }

        [TechTalk.SpecRun.FeatureCleanup()]
        public virtual void FeatureTearDown()
        {
            testRunner.OnFeatureEnd();
            testRunner = null;
        }

        public virtual void TestInitialize()
        {
        }

        [TechTalk.SpecRun.ScenarioCleanup()]
        public virtual void ScenarioTearDown()
        {
            testRunner.OnScenarioEnd();
        }

        public virtual void ScenarioSetup(TechTalk.SpecFlow.ScenarioInfo scenarioInfo)
        {
            testRunner.OnScenarioStart(scenarioInfo);
        }

        public virtual void ScenarioCleanup()
        {
            testRunner.CollectScenarioErrors();
        }

        public virtual void ThisIsAScenarioOutlineWhereAllScenariosPass(string result, string[] exampleTags)
        {
            TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("This is a scenario outline where all scenarios pass", exampleTags);
#line 4
this.ScenarioSetup(scenarioInfo);
#line 8
  testRunner.Then(string.Format("the scenario will \'{0}\'", result), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
            this.ScenarioCleanup();
        }

        [TechTalk.SpecRun.ScenarioAttribute("This is a scenario outline where all scenarios pass, pass_1", Description="\nThis means the entire scenario outline passes.", SourceLine=11)]
        public virtual void ThisIsAScenarioOutlineWhereAllScenariosPass_Pass_1()
        {
            this.ThisIsAScenarioOutlineWhereAllScenariosPass("pass_1", ((string[])(null)));
        }

        [TechTalk.SpecRun.ScenarioAttribute("This is a scenario outline where all scenarios pass, pass_2", Description="\nThis means the entire scenario outline passes.", SourceLine=12)]
        public virtual void ThisIsAScenarioOutlineWhereAllScenariosPass_Pass_2()
        {
            this.ThisIsAScenarioOutlineWhereAllScenariosPass("pass_2", ((string[])(null)));
        }

        [TechTalk.SpecRun.ScenarioAttribute("This is a scenario outline where all scenarios pass, pass_3", Description="\nThis means the entire scenario outline passes.", SourceLine=13)]
        public virtual void ThisIsAScenarioOutlineWhereAllScenariosPass_Pass_3()
        {
            this.ThisIsAScenarioOutlineWhereAllScenariosPass("pass_3", ((string[])(null)));
        }

        public virtual void ThisIsAScenarioOutlineWhereOneScenarioIsInconclusive(string result, string[] exampleTags)
        {
            TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("This is a scenario outline where one scenario is inconclusive", exampleTags);
#line 17
this.ScenarioSetup(scenarioInfo);
#line 21
  testRunner.Then(string.Format("the scenario will \'{0}\'", result), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
            this.ScenarioCleanup();
        }

        [TechTalk.SpecRun.ScenarioAttribute("This is a scenario outline where one scenario is inconclusive, pass_1", Description="\nThis means the entire scenario outline is inconclusive.", SourceLine=24)]
        public virtual void ThisIsAScenarioOutlineWhereOneScenarioIsInconclusive_Pass_1()
        {
            this.ThisIsAScenarioOutlineWhereOneScenarioIsInconclusive("pass_1", ((string[])(null)));
        }

        [TechTalk.SpecRun.ScenarioAttribute("This is a scenario outline where one scenario is inconclusive, pass_2", Description="\nThis means the entire scenario outline is inconclusive.", SourceLine=25)]
        public virtual void ThisIsAScenarioOutlineWhereOneScenarioIsInconclusive_Pass_2()
        {
            this.ThisIsAScenarioOutlineWhereOneScenarioIsInconclusive("pass_2", ((string[])(null)));
        }

        [TechTalk.SpecRun.ScenarioAttribute("This is a scenario outline where one scenario is inconclusive, inconclusive_1", Description="\nThis means the entire scenario outline is inconclusive.", SourceLine=26)]
        public virtual void ThisIsAScenarioOutlineWhereOneScenarioIsInconclusive_Inconclusive_1()
        {
            this.ThisIsAScenarioOutlineWhereOneScenarioIsInconclusive("inconclusive_1", ((string[])(null)));
        }

        public virtual void ThisIsAScenarioOutlineWhereOneScenarioFails(string result, string[] exampleTags)
        {
            TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("This is a scenario outline where one scenario fails", exampleTags);
#line 30
this.ScenarioSetup(scenarioInfo);
#line 34
  testRunner.Then(string.Format("the scenario will \'{0}\'", result), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
            this.ScenarioCleanup();
        }

        [TechTalk.SpecRun.ScenarioAttribute("This is a scenario outline where one scenario fails, pass_1", Description="\nThis means the entire scenario outline fails.", SourceLine=37)]
        public virtual void ThisIsAScenarioOutlineWhereOneScenarioFails_Pass_1()
        {
            this.ThisIsAScenarioOutlineWhereOneScenarioFails("pass_1", ((string[])(null)));
        }

        [TechTalk.SpecRun.ScenarioAttribute("This is a scenario outline where one scenario fails, pass_2", Description="\nThis means the entire scenario outline fails.", SourceLine=38)]
        public virtual void ThisIsAScenarioOutlineWhereOneScenarioFails_Pass_2()
        {
            this.ThisIsAScenarioOutlineWhereOneScenarioFails("pass_2", ((string[])(null)));
        }

        [TechTalk.SpecRun.ScenarioAttribute("This is a scenario outline where one scenario fails, fail_1", Description="\nThis means the entire scenario outline fails.", SourceLine=39)]
        public virtual void ThisIsAScenarioOutlineWhereOneScenarioFails_Fail_1()
        {
            this.ThisIsAScenarioOutlineWhereOneScenarioFails("fail_1", ((string[])(null)));
        }

        public virtual void AndWeCanGoTotallyBonkersWithMultipleExampleSections_(string result, string[] exampleTags)
        {
            TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("And we can go totally bonkers with multiple example sections.", exampleTags);
#line 43
this.ScenarioSetup(scenarioInfo);
#line 45
  testRunner.Then(string.Format("the scenario will \'{0}\'", result), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
            this.ScenarioCleanup();
        }

        [TechTalk.SpecRun.ScenarioAttribute("And we can go totally bonkers with multiple example sections., Examples 1, pass_1" +
            "", SourceLine=48)]
        public virtual void AndWeCanGoTotallyBonkersWithMultipleExampleSections__ExampleSet0_Pass_1()
        {
            this.AndWeCanGoTotallyBonkersWithMultipleExampleSections_("pass_1", ((string[])(null)));
        }

        [TechTalk.SpecRun.ScenarioAttribute("And we can go totally bonkers with multiple example sections., Examples 1, pass_2" +
            "", SourceLine=49)]
        public virtual void AndWeCanGoTotallyBonkersWithMultipleExampleSections__ExampleSet0_Pass_2()
        {
            this.AndWeCanGoTotallyBonkersWithMultipleExampleSections_("pass_2", ((string[])(null)));
        }

        [TechTalk.SpecRun.ScenarioAttribute("And we can go totally bonkers with multiple example sections., Examples 2, inconc" +
            "lusive_1", SourceLine=53)]
        public virtual void AndWeCanGoTotallyBonkersWithMultipleExampleSections__ExampleSet1_Inconclusive_1()
        {
            this.AndWeCanGoTotallyBonkersWithMultipleExampleSections_("inconclusive_1", ((string[])(null)));
        }

        [TechTalk.SpecRun.ScenarioAttribute("And we can go totally bonkers with multiple example sections., Examples 2, inconc" +
            "lusive_2", SourceLine=54)]
        public virtual void AndWeCanGoTotallyBonkersWithMultipleExampleSections__ExampleSet1_Inconclusive_2()
        {
            this.AndWeCanGoTotallyBonkersWithMultipleExampleSections_("inconclusive_2", ((string[])(null)));
        }

        [TechTalk.SpecRun.ScenarioAttribute("And we can go totally bonkers with multiple example sections., Examples 3, fail_1" +
            "", SourceLine=58)]
        public virtual void AndWeCanGoTotallyBonkersWithMultipleExampleSections__ExampleSet2_Fail_1()
        {
            this.AndWeCanGoTotallyBonkersWithMultipleExampleSections_("fail_1", ((string[])(null)));
        }

        [TechTalk.SpecRun.ScenarioAttribute("And we can go totally bonkers with multiple example sections., Examples 3, fail_2" +
            "", SourceLine=59)]
        public virtual void AndWeCanGoTotallyBonkersWithMultipleExampleSections__ExampleSet2_Fail_2()
        {
            this.AndWeCanGoTotallyBonkersWithMultipleExampleSections_("fail_2", ((string[])(null)));
        }

        public virtual void DealCorrectlyWithBackslashesInTheExamples(string filePath, string[] exampleTags)
        {
            TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Deal correctly with backslashes in the examples", exampleTags);
#line 63
this.ScenarioSetup(scenarioInfo);
#line 65
  testRunner.When(string.Format("I have backslashes in the value, for example a \'{0}\'", filePath), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line hidden
            this.ScenarioCleanup();
        }

        [TechTalk.SpecRun.ScenarioAttribute("Deal correctly with backslashes in the examples, c:\\Temp\\", SourceLine=68)]
        public virtual void DealCorrectlyWithBackslashesInTheExamples_CTemp()
        {
            this.DealCorrectlyWithBackslashesInTheExamples("c:\\Temp\\", ((string[])(null)));
        }

        public virtual void DealCorrectlyWithParenthesisInTheExamples(string overlyDescriptiveField, string[] exampleTags)
        {
            TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Deal correctly with parenthesis in the examples", exampleTags);
#line 72
this.ScenarioSetup(scenarioInfo);
#line 74
  testRunner.When(string.Format("I have parenthesis in the value, for example an \'{0}\'", overlyDescriptiveField), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line hidden
            this.ScenarioCleanup();
        }

        [TechTalk.SpecRun.ScenarioAttribute("Deal correctly with parenthesis in the examples, This is a description (and more)" +
            "", SourceLine=77)]
        public virtual void DealCorrectlyWithParenthesisInTheExamples_ThisIsADescriptionAndMore()
        {
            this.DealCorrectlyWithParenthesisInTheExamples("This is a description (and more)", ((string[])(null)));
        }

        public virtual void DealCorrectlyWithOverlongExampleValues(string value1, string value2, string[] exampleTags)
        {
            TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Deal correctly with overlong example values", exampleTags);
#line 80
 this.ScenarioSetup(scenarioInfo);
#line 82
  testRunner.When("I have a field with value \'<value>\'", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line 83
  testRunner.Then("the scenario will \'pass_1\'", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
            this.ScenarioCleanup();
        }

        [TechTalk.SpecRun.ScenarioAttribute("Deal correctly with overlong example values, Please enter a valid two letter coun" +
            "try code (e.g. DE)!", SourceLine=86)]
        public virtual void DealCorrectlyWithOverlongExampleValues_PleaseEnterAValidTwoLetterCountryCodeE_G_DE()
        {
            this.DealCorrectlyWithOverlongExampleValues("Please enter a valid two letter country code (e.g. DE)!", "This is just a very very very veery long error message!", ((string[])(null)));
        }

        [TechTalk.SpecRun.TestRunCleanup()]
        public virtual void TestRunCleanup()
        {
TechTalk.SpecFlow.TestRunnerManager.GetTestRunner().OnTestRunEnd();
        }
    }
}
#pragma warning restore
#endregion


text:
package javac

import (
	"github.com/godfried/impendulo/config"
	"github.com/godfried/impendulo/tool"
	"github.com/godfried/impendulo/tool/result"
	"labix.org/v2/mgo/bson"

	"time"
)

type (
	Tool struct {
		cmd string
		cp  string
	}
)

//New creates a new javac instance. cp is the classpath used when compiling.
func New(cp string) (*Tool, error) {
	p, e := config.JAVAC.Path()
	if e != nil {
		return nil, e
	}
	return &Tool{cp: cp, cmd: p}, nil
}

//Lang is Java.
func (t *Tool) Lang() tool.Language {
	return tool.JAVA
}

//Name is Javac
func (t *Tool) Name() string {
	return NAME
}

func (t *Tool) AddCP(s string) {
	if t.cp != "" {
		t.cp += ":"
	}
	t.cp += s
}

//Run compiles the Java source file specified by t. We compile with maximum warnings and compile
//classes implicitly loaded by the source code. All compilation results will be stored (success,
//errors and warnings).
func (t *Tool) Run(fileId bson.ObjectId, target *tool.Target) (result.Tooler, error) {
	cp := t.cp
	if cp != "" {
		cp += ":"
	}
	cp += target.Dir
	a := []string{t.cmd, "-cp", cp + ":" + target.Dir, "-implicit:class", "-Xlint", target.FilePath()}
	r, e := tool.RunCommand(a, nil, 30*time.Second)
	if e != nil {
		if !tool.IsEndError(e) {
			return nil, e
		}
		return NewResult(fileId, r.StdErr), tool.NewCompileError(target.FullName(), string(r.StdErr))
	} else if r.HasStdErr() {
		//Compiler warnings.
		return NewResult(fileId, r.StdErr), nil
	}
	return NewResult(fileId, result.COMPILE_SUCCESS), nil
}


text:
import os
module = os.environ.get('DJANGO_SETTINGS_MODULE', 'settings')
exec('import %s as module' % module)
MIDDLEWARE_CLASSES, INSTALLED_APPS = module.MIDDLEWARE_CLASSES, module.INSTALLED_APPS

MIDDLEWARE_CLASSES = MIDDLEWARE_CLASSES + ('limbo.middleware.AdminDebugToolbarMiddleware', )

INSTALLED_APPS = INSTALLED_APPS + ('debug_toolbar', )

def add_network(*interfaces):
    try:
        from settings import INTERNAL_IPS as internal_ips
        if not internal_ips:
            internal_ips = ()
    except ImportError:
        internal_ips = ('127.0.0.1',)
    try:
        from limbo.ip_address import get_ip_address
        for iface in interfaces:
            internal_ips = internal_ips + ('.'.join(get_ip_address(iface).split('.')[:-1]) + '.0/24', )
    except Exception:
        import traceback
        traceback.print_exc()
    return internal_ips


text:
package net.sf.mmm.util.date.api;

import java.util.Calendar;

import net.sf.mmm.util.exception.api.IllegalCaseException;
import net.sf.mmm.util.exception.api.NlsNullPointerException;
import net.sf.mmm.util.lang.api.SimpleDatatype;

/**
 * The enum contains the seven days of a week in Gregorian calendar.
 *
 * @author Joerg Hohwiller (hohwille at users.sourceforge.net)
 * @since 1.0.0
 */
public enum Weekday implements SimpleDatatype<String> {

  /** The according weekday. */
  MONDAY("Mo", "Monday", Calendar.MONDAY),

  /** The according weekday. */
  TUESDAY("Tu", "Tuesday", Calendar.TUESDAY),

  /** The according weekday. */
  WEDNESDAY("We", "Wednesday", Calendar.WEDNESDAY),

  /** The according weekday. */
  THURSDAY("Th", "Thursday", Calendar.THURSDAY),

  /** The according weekday. */
  FRIDAY("Fr", "Friday", Calendar.FRIDAY),

  /** The according weekday. */
  SATURDAY("Sa", "Saturday", Calendar.SATURDAY),

  /** The according weekday. */
  SUNDAY("Su", "Sunday", Calendar.SUNDAY);

  private final String value;

  private final String title;

  private final int calendarId;

  /**
   * The constructor.
   *
   * @param value - see {@link #getValue()}.
   * @param title - see {@link #toString()}.
   * @param calendarId - see {@link #getCalendarId()}.
   */
  private Weekday(String value, String title, int calendarId) {

    this.value = value;
    this.title = title;
    this.calendarId = calendarId;
  }

  /**
   * This method gets the next {@link Weekday} for this {@link Weekday}.
   *
   * @return the {@link Weekday} one day after this {@link Weekday}.
   */
  public Weekday getNext() {

    switch (this) {
      case MONDAY:
        return TUESDAY;
      case TUESDAY:
        return WEDNESDAY;
      case WEDNESDAY:
        return THURSDAY;
      case THURSDAY:
        return FRIDAY;
      case FRIDAY:
        return SATURDAY;
      case SATURDAY:
        return SUNDAY;
      case SUNDAY:
        return MONDAY;
      default:
        throw new IllegalCaseException(Weekday.class, this);
    }
  }

  /**
   * This method gets the previous {@link Weekday} for this {@link Weekday}.
   *
   * @return the {@link Weekday} one day before this {@link Weekday}.
   */
  public Weekday getPrevious() {

    switch (this) {
      case MONDAY:
        return SUNDAY;
      case TUESDAY:
        return MONDAY;
      case WEDNESDAY:
        return TUESDAY;
      case THURSDAY:
        return WEDNESDAY;
      case FRIDAY:
        return THURSDAY;
      case SATURDAY:
        return FRIDAY;
      case SUNDAY:
        return SATURDAY;
      default:
        throw new IllegalCaseException(Weekday.class, this);
    }
  }

  @Override
  public String getValue() {

    return this.value;
  }

  /**
   * This method {@link Calendar#set(int, int) sets} this {@link Weekday} in the given {@code calendar}.
   *
   * @param calendar is the {@link Calendar}.
   */
  public void setWeekday(Calendar calendar) {

    NlsNullPointerException.checkNotNull(Calendar.class, calendar);
    calendar.set(Calendar.DAY_OF_WEEK, getCalendarId());
  }

  /**
   * This method gets the ID constant of {@link java.util.Calendar} representing this {@link Weekday}. This is the
   * Christian representation where {@link #SUNDAY} is the first day of the week represented with 1. The enum constants
   * of {@link Weekday} are ordered such that {@link #MONDAY} comes first, so you can use {@link #ordinal()} for other
   * representation. Please note that {@link #ordinal()} is {@code 0} based so you might want to increment the result.
   *
   * @return the calendar ID.
   */
  public int getCalendarId() {

    return this.calendarId;
  }

  /**
   * This method returns the {@link Weekday} resulting if the given number of {@code days} are elapsed after the current
   * {@link Weekday} (this). The {@link Weekday} will wrap so {@link #add(int) add(7)} will return the {@link Weekday}
   * itself (this) just like {@link #add(int) add(0)} or e.g. {@link #add(int) add(-14)}.
   *
   * @param days are the number of days to add. May be negative to subtract or zero ({@code 0}) for no change.
   * @return the resulting {@link Weekday}.
   */
  public Weekday add(int days) {

    int sum = (ordinal() + days) % 7;
    for (Weekday weekday : values()) {
      if (weekday.ordinal() == sum) {
        return weekday;
      }
    }
    throw new IllegalCaseException(this.title + "+" + days);
  }

  @Override
  public String toString() {

    return this.title;
  }

  /**
   * This method gets the {@link Weekday} for the given {@code value}.
   *
   * @param value is the {@link #getValue() value} of the requested {@link Weekday}.
   * @return the requested {@link Weekday} or {@code null} if no such {@link Weekday} exists.
   */
  public static Weekday fromValue(String value) {

    for (Weekday instance : values()) {
      if (instance.value.equals(value)) {
        return instance;
      }
    }
    return null;
  }

  /**
   * This method gets the {@link Weekday} from the given {@code calendar}.
   *
   * @param calendar is the {@link Calendar}.
   * @return the {@link Weekday} representing the {@link Calendar#DAY_OF_WEEK weekday} of the given {@link Calendar}.
   */
  public static Weekday fromCalendar(Calendar calendar) {

    NlsNullPointerException.checkNotNull(Calendar.class, calendar);
    int result = calendar.get(Calendar.DAY_OF_WEEK);
    for (Weekday weekday : values()) {
      if (weekday.getCalendarId() == result) {
        return weekday;
      }
    }
    throw new IllegalCaseException(Integer.toString(result));
  }

  /**
   * This method gets the {@link Weekday} from the given {@code calendar}.
   *
   * @param calendarId is the {@link #getCalendarId() calendar ID}.
   * @return the {@link Weekday} representing the {@link #getCalendarId() calendar ID} or {@code null} if no such
   *         {@link Weekday} exists (illegal {@code calendarId}).
   */
  public static Weekday fromCalendarId(int calendarId) {

    for (Weekday weekday : values()) {
      if (weekday.getCalendarId() == calendarId) {
        return weekday;
      }
    }
    return null;
  }

}


text:
//当前显示的 menuitem。$(' ') 当中的空格字符不能少
var displayFunctionMenu = $(' ');

//定义全局的 jQuery 对象,用于加速 jQuery 的搜寻速度,因为 index.html 文件太大
var jMenuItem;
var jCategoryItem;
var jCurrentItem;
var jCurrentContent;

function document_ready()
{
	//文档加载完后,为 jMenuItem 和 jCategoryItem 赋值
	jMenuItem = $('body > .mainmenu > .menuitem');
	jCategoryItem = jMenuItem.next('.functionmenu').children('.categoryitem');

	var englishCheckbox = $('#english');

	//menuitem 单击事件
	jMenuItem.click(function(e){
		displayFunctionMenu.hide().prev('.menuitem').removeClass('selecteditem');
		displayFunctionMenu = $(e.target).addClass('selecteditem').next('.functionmenu').show();
		jCurrentItem = displayFunctionMenu.children(".category").children(".selecteditem");
		jCurrentContent = jCurrentItem.next('.content');

	});

	//categoryitem 单击事件
	jCategoryItem.click(function(e){
		$(e.target).next('.category').toggle();
	});

	///////////////

	function functionitem_click(o)
	{
		// 已有显示项目
		if (jCurrentItem) {
			jCurrentItem.removeClass('selecteditem');
			jCurrentContent.hide();
		}
		jCurrentItem = $(o.target);
		jCurrentContent = jCurrentItem.next('.content');
		jCurrentItem.addClass('selecteditem');
		var scrollTop = $(window).scrollTop();
		jCurrentContent.css("top",scrollTop>77 ? scrollTop-71 : 0).show();
	}

	function functioncontent_cornerize(o)
	{
		//设置 content 圆角
		$(o.target).next('.content').corner();
	}

	//将未分类的function的事件绑定
	jMenuItem.next('.functionmenu').children('.non-category').children('.functionitem')
	.click(functionitem_click)
	.one('click', functioncontent_cornerize);

	//将 functionitem 单击事件的绑定推迟至 categoryitem 被单击之后,并且设置 content 圆角。推迟绑定事件是为是优化性能
	jCategoryItem.one('click',function(e){
		//functionitem 单击事件
		$(e.target).next('.category').children('.functionitem')
		.click(functionitem_click)
		.one('click', functioncontent_cornerize);
	});

	/////////////

	//Fold button 事件
	$('#fold').click(function(){
		displayFunctionMenu.children('.category').hide();
	});

	//Expand button 事件
	$('#expand').click(function(){
		//以触发 categoryitem 的单击事件来代替直接的 show category,以免错过由 categoryitem 引发的 functionitem 单击事件绑定
		displayFunctionMenu.children('.category:hidden').prev('.categoryitem').click();

	});

	//Fold all button 事件
	$('#foldall').click(function(){
		jCategoryItem.next('.category').hide();
	});

	//Expand all button 事件;首次单击的时候,会触发 categoryitem 的单击事件来代替直接的 show category,可以使 functionitem 单击事件能顺利绑定
	$('#expandall').one('click',function(e){
		jCategoryItem.click().next('.category').show();
		//Expand all button 单击事件
		$('#expandall').click(function(){
			jCategoryItem.next('.category').show();
		});
	});

	///////////////////////////////////////////////////////////////////////////////////////////////////////

	$("body > .mainmenu > .functionmenu .content").draggable();

	var itemsToDrag = jMenuItem.add(jCategoryItem).add("body > .mainmenu > .functionmenu .functionitem");

	itemsToDrag.draggable({
		 revert: 'invalid',
		 //stack: { group: '.parent .self', min: 1 },
		 zIndex: 1200
	 });

	$("body > .mainmenu > .menuitem").droppable({
		tolerance: 'pointer',
		drop: function(ev, ui){
			alert("dropped!");
		}
	});

/*
	var itemsToSortString = "body > .mainmenu, body > .mainmenu > .functionmenu, body > .mainmenu > .functionmenu > .category";

	$(itemsToSortString).sortable({
		items: '> *:not(.non-category)'
		//connectWith: itemsToSortString.split(',')
	});
*/

	$('.browse_button').toggle(function() {

		var iframe = '<iframe src="' + $(this).attr('url') +'"></iframe>';
		$(this).after(iframe);

		$(this).val("点击这里关闭页面");
	},

	function () {
		$(this).next("iframe").remove();
		$(this).val("点击这里访问页面");
	});

}


text:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleInstances #-}

module Api.InfoService (InfoService, infoServiceApiInit)
where

import           Snap.Snaplet
import           Snap.Core
import qualified Data.ByteString.Char8 as B
import qualified Data.CaseInsensitive as CI
import Data.Aeson
import Control.Lens
import Control.Monad.State.Class
import Control.Monad.Trans (liftIO)

import Lib

data InfoService = InfoService

makeLenses ''InfoService

infoApiRoutes :: [(B.ByteString, Handler b InfoService ())]
infoApiRoutes = [("info", method GET getInfo)
                ,("env", withAuth $ method GET getEnv)
                ,("config", method GET getConfig)
                ,("getremoteip", method GET getRemoteIP)]

getInfo :: Handler b InfoService ()
getInfo = do
  modifyResponse $ setHeader "Content-Type" "application/json"
  modifyResponse $ setResponseCode 200
  writeText "{\"name\":\"hueb service\",\"description\":\"Provides base template to start new web services in haskell\",\"status\": \"UP\"}"

getEnv :: Handler b InfoService ()
getEnv = do
  modifyResponse $ setHeader "Content-Type" "application/json"
  modifyResponse $ setResponseCode 200
  writeText "env protected endpoint"

getConfig :: Handler b InfoService ()
getConfig = do
  r <- doRequest
  writeLBS . encode $ map (\(x,y) -> (B.unpack $ CI.original x, B.unpack y)) $ listHeaders r

getRemoteIP :: Handler b InfoService ()
getRemoteIP = do
  r <- doRequest
  writeBS $ rqRemoteAddr r

doRequest :: Handler b InfoService Request
doRequest = do
  modifyResponse $ setHeader "Content-Type" "application/json"
  modifyResponse $ setResponseCode 200
  getRequest

infoServiceApiInit :: SnapletInit b InfoService
infoServiceApiInit = makeSnaplet "infoService" "Provies info and health endpoints to reports healthiness of the service" Nothing $ do
                      addRoutes infoApiRoutes
                      return InfoService


text:
import java.awt.*;
import java.awt.geom.*;
public class Checkpoint {
	public double x;
	public double y;

	private double width = 8;

	public Checkpoint(double x, double y){
		this.x = x;
		this.y = y;
	}

	public Shape getShape(){
		return new Rectangle2D.Double(x, y, width, width);
	}
}


text:
package com.alice.a7blankproject.model;

public class CurrencyInfo {
    private String code;
    private String name;
    private double exchangeRate;

    public CurrencyInfo(String code, String name, double exchangeRate) {
        this.code = code.trim();
        this.name = name.trim();
        this.exchangeRate = exchangeRate;
    }

    public String getName() {
        return this.name;
    }

    public String getCode() {
        return this.code;
    }

    public double getExchangeRate() {
        return this.exchangeRate;
    }

    @Override
    public String toString() {
        return getCode() + " ("
                + getName() + "): "
                + getExchangeRate();
    }
}


text:
package com.squareup.okhttp.internal.http;

import com.squareup.okhttp.Address;
import com.squareup.okhttp.Connection;
import com.squareup.okhttp.ConnectionPool;
import com.squareup.okhttp.OkAuthenticator;
import com.squareup.okhttp.Protocol;
import com.squareup.okhttp.RouteDatabase;
import com.squareup.okhttp.internal.Dns;
import com.squareup.okhttp.internal.SslContextBuilder;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSocketFactory;
import org.junit.Test;

import static java.net.Proxy.NO_PROXY;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public final class RouteSelectorTest {
  private static final int proxyAPort = 1001;
  private static final String proxyAHost = "proxyA";
  private static final Proxy proxyA =
      new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyAHost, proxyAPort));
  private static final int proxyBPort = 1002;
  private static final String proxyBHost = "proxyB";
  private static final Proxy proxyB =
      new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyBHost, proxyBPort));
  private static final URI uri;
  private static final String uriHost = "hostA";
  private static final int uriPort = 80;

  private static final SSLContext sslContext = SslContextBuilder.localhost();
  private static final SSLSocketFactory socketFactory = sslContext.getSocketFactory();
  private static final HostnameVerifier hostnameVerifier;
  private static final ConnectionPool pool;

  static {
    try {
      uri = new URI("http://" + uriHost + ":" + uriPort + "/path");
      pool = ConnectionPool.getDefault();
      hostnameVerifier = HttpsURLConnectionImpl.getDefaultHostnameVerifier();
    } catch (Exception e) {
      throw new AssertionError(e);
    }
  }

  private final OkAuthenticator authenticator = HttpAuthenticator.SYSTEM_DEFAULT;
  private final List<Protocol> protocols = Arrays.asList(Protocol.HTTP_11);
  private final FakeDns dns = new FakeDns();
  private final FakeProxySelector proxySelector = new FakeProxySelector();

  @Test public void singleRoute() throws Exception {
    Address address = new Address(uriHost, uriPort, null, null, authenticator, null, protocols);
    RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
        new RouteDatabase());

    assertTrue(routeSelector.hasNext());
    dns.inetAddresses = makeFakeAddresses(255, 1);
    assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort,
        false);
    dns.assertRequests(uriHost);

    assertFalse(routeSelector.hasNext());
    try {
      routeSelector.next("GET");
      fail();
    } catch (NoSuchElementException expected) {
    }
  }

  @Test public void singleRouteReturnsFailedRoute() throws Exception {
    Address address = new Address(uriHost, uriPort, null, null, authenticator, null, protocols);
    RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
        new RouteDatabase());

    assertTrue(routeSelector.hasNext());
    dns.inetAddresses = makeFakeAddresses(255, 1);
    Connection connection = routeSelector.next("GET");
    RouteDatabase routeDatabase = new RouteDatabase();
    routeDatabase.failed(connection.getRoute());
    routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns, routeDatabase);
    assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort,
        false);
    assertFalse(routeSelector.hasNext());
    try {
      routeSelector.next("GET");
      fail();
    } catch (NoSuchElementException expected) {
    }
  }

  @Test public void explicitProxyTriesThatProxiesAddressesOnly() throws Exception {
    Address address = new Address(uriHost, uriPort, null, null, authenticator, proxyA, protocols);
    RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
        new RouteDatabase());

    assertTrue(routeSelector.hasNext());
    dns.inetAddresses = makeFakeAddresses(255, 2);
    assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[0], proxyAPort,
        false);
    assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[1], proxyAPort,
        false);

    assertFalse(routeSelector.hasNext());
    dns.assertRequests(proxyAHost);
    proxySelector.assertRequests(); // No proxy selector requests!
  }

  @Test public void explicitDirectProxy() throws Exception {
    Address address = new Address(uriHost, uriPort, null, null, authenticator, NO_PROXY,
        protocols);
    RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
        new RouteDatabase());

    assertTrue(routeSelector.hasNext());
    dns.inetAddresses = makeFakeAddresses(255, 2);
    assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort,
        false);
    assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[1], uriPort,
        false);

    assertFalse(routeSelector.hasNext());
    dns.assertRequests(uri.getHost());
    proxySelector.assertRequests(); // No proxy selector requests!
  }

  @Test public void proxySelectorReturnsNull() throws Exception {
    Address address = new Address(uriHost, uriPort, null, null, authenticator, null, protocols);

    proxySelector.proxies = null;
    RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
        new RouteDatabase());
    proxySelector.assertRequests(uri);

    assertTrue(routeSelector.hasNext());
    dns.inetAddresses = makeFakeAddresses(255, 1);
    assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort,
        false);
    dns.assertRequests(uriHost);

    assertFalse(routeSelector.hasNext());
  }

  @Test public void proxySelectorReturnsNoProxies() throws Exception {
    Address address = new Address(uriHost, uriPort, null, null, authenticator, null, protocols);
    RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
        new RouteDatabase());

    assertTrue(routeSelector.hasNext());
    dns.inetAddresses = makeFakeAddresses(255, 2);
    assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort,
        false);
    assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[1], uriPort,
        false);

    assertFalse(routeSelector.hasNext());
    dns.assertRequests(uri.getHost());
    proxySelector.assertRequests(uri);
  }

  @Test public void proxySelectorReturnsMultipleProxies() throws Exception {
    Address address = new Address(uriHost, uriPort, null, null, authenticator, null, protocols);

    proxySelector.proxies.add(proxyA);
    proxySelector.proxies.add(proxyB);
    RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
        new RouteDatabase());
    proxySelector.assertRequests(uri);

    // First try the IP addresses of the first proxy, in sequence.
    assertTrue(routeSelector.hasNext());
    dns.inetAddresses = makeFakeAddresses(255, 2);
    assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[0], proxyAPort,
        false);
    assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[1], proxyAPort,
        false);
    dns.assertRequests(proxyAHost);

    // Next try the IP address of the second proxy.
    assertTrue(routeSelector.hasNext());
    dns.inetAddresses = makeFakeAddresses(254, 1);
    assertConnection(routeSelector.next("GET"), address, proxyB, dns.inetAddresses[0], proxyBPort,
        false);
    dns.assertRequests(proxyBHost);

    // Finally try the only IP address of the origin server.
    assertTrue(routeSelector.hasNext());
    dns.inetAddresses = makeFakeAddresses(253, 1);
    assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort,
        false);
    dns.assertRequests(uriHost);

    assertFalse(routeSelector.hasNext());
  }

  @Test public void proxySelectorDirectConnectionsAreSkipped() throws Exception {
    Address address = new Address(uriHost, uriPort, null, null, authenticator, null, protocols);

    proxySelector.proxies.add(NO_PROXY);
    RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
        new RouteDatabase());
    proxySelector.assertRequests(uri);

    // Only the origin server will be attempted.
    assertTrue(routeSelector.hasNext());
    dns.inetAddresses = makeFakeAddresses(255, 1);
    assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort,
        false);
    dns.assertRequests(uriHost);

    assertFalse(routeSelector.hasNext());
  }

  @Test public void proxyDnsFailureContinuesToNextProxy() throws Exception {
    Address address = new Address(uriHost, uriPort, null, null, authenticator, null, protocols);

    proxySelector.proxies.add(proxyA);
    proxySelector.proxies.add(proxyB);
    proxySelector.proxies.add(proxyA);
    RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
        new RouteDatabase());
    proxySelector.assertRequests(uri);

    assertTrue(routeSelector.hasNext());
    dns.inetAddresses = makeFakeAddresses(255, 1);
    assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[0], proxyAPort,
        false);
    dns.assertRequests(proxyAHost);

    assertTrue(routeSelector.hasNext());
    dns.inetAddresses = null;
    try {
      routeSelector.next("GET");
      fail();
    } catch (UnknownHostException expected) {
    }
    dns.assertRequests(proxyBHost);

    assertTrue(routeSelector.hasNext());
    dns.inetAddresses = makeFakeAddresses(255, 1);
    assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[0], proxyAPort,
        false);
    dns.assertRequests(proxyAHost);

    assertTrue(routeSelector.hasNext());
    dns.inetAddresses = makeFakeAddresses(254, 1);
    assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort,
        false);
    dns.assertRequests(uriHost);

    assertFalse(routeSelector.hasNext());
  }

  // https://github.com/square/okhttp/issues/442
  @Test public void nonSslErrorAddsAllTlsModesToFailedRoute() throws Exception {
    Address address = new Address(uriHost, uriPort, socketFactory, hostnameVerifier, authenticator,
        Proxy.NO_PROXY, protocols);
    RouteDatabase routeDatabase = new RouteDatabase();
    RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
        routeDatabase);

    dns.inetAddresses = makeFakeAddresses(255, 1);
    Connection connection = routeSelector.next("GET");
    routeSelector.connectFailed(connection, new IOException("Non SSL exception"));
    assertTrue(routeDatabase.failedRoutesCount() == 2);
    assertFalse(routeSelector.hasNext());
  }

  @Test public void sslErrorAddsOnlyFailedTlsModeToFailedRoute() throws Exception {
    Address address = new Address(uriHost, uriPort, socketFactory, hostnameVerifier, authenticator,
        Proxy.NO_PROXY, protocols);
    RouteDatabase routeDatabase = new RouteDatabase();
    RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
        routeDatabase);

    dns.inetAddresses = makeFakeAddresses(255, 1);
    Connection connection = routeSelector.next("GET");
    routeSelector.connectFailed(connection, new SSLHandshakeException("SSL exception"));
    assertTrue(routeDatabase.failedRoutesCount() == 1);
    assertTrue(routeSelector.hasNext());
  }

  @Test public void multipleProxiesMultipleInetAddressesMultipleTlsModes() throws Exception {
    Address address = new Address(uriHost, uriPort, socketFactory, hostnameVerifier, authenticator,
        null, protocols);
    proxySelector.proxies.add(proxyA);
    proxySelector.proxies.add(proxyB);
    RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
        new RouteDatabase());

    // Proxy A
    dns.inetAddresses = makeFakeAddresses(255, 2);
    assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[0], proxyAPort,
        true);
    dns.assertRequests(proxyAHost);
    assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[0], proxyAPort,
        false);
    assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[1], proxyAPort,
        true);
    assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[1], proxyAPort,
        false);

    // Proxy B
    dns.inetAddresses = makeFakeAddresses(254, 2);
    assertConnection(routeSelector.next("GET"), address, proxyB, dns.inetAddresses[0], proxyBPort,
        true);
    dns.assertRequests(proxyBHost);
    assertConnection(routeSelector.next("GET"), address, proxyB, dns.inetAddresses[0], proxyBPort,
        false);
    assertConnection(routeSelector.next("GET"), address, proxyB, dns.inetAddresses[1], proxyBPort,
        true);
    assertConnection(routeSelector.next("GET"), address, proxyB, dns.inetAddresses[1], proxyBPort,
        false);

    // Origin
    dns.inetAddresses = makeFakeAddresses(253, 2);
    assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort,
        true);
    dns.assertRequests(uriHost);
    assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort,
        false);
    assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[1], uriPort,
        true);
    assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[1], uriPort,
        false);

    assertFalse(routeSelector.hasNext());
  }

  @Test public void failedRoutesAreLast() throws Exception {
    Address address = new Address(uriHost, uriPort, socketFactory, hostnameVerifier, authenticator,
        Proxy.NO_PROXY, protocols);

    RouteDatabase routeDatabase = new RouteDatabase();
    RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
        routeDatabase);
    dns.inetAddresses = makeFakeAddresses(255, 1);

    // Extract the regular sequence of routes from selector.
    List<Connection> regularRoutes = new ArrayList<Connection>();
    while (routeSelector.hasNext()) {
      regularRoutes.add(routeSelector.next("GET"));
    }

    // Check that we do indeed have more than one route.
    assertTrue(regularRoutes.size() > 1);
    // Add first regular route as failed.
    routeDatabase.failed(regularRoutes.get(0).getRoute());
    // Reset selector
    routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns, routeDatabase);

    List<Connection> routesWithFailedRoute = new ArrayList<Connection>();
    while (routeSelector.hasNext()) {
      routesWithFailedRoute.add(routeSelector.next("GET"));
    }

    assertEquals(regularRoutes.get(0).getRoute(),
        routesWithFailedRoute.get(routesWithFailedRoute.size() - 1).getRoute());
    assertEquals(regularRoutes.size(), routesWithFailedRoute.size());
  }

  private void assertConnection(Connection connection, Address address, Proxy proxy,
      InetAddress socketAddress, int socketPort, boolean modernTls) {
    assertEquals(address, connection.getRoute().getAddress());
    assertEquals(proxy, connection.getRoute().getProxy());
    assertEquals(socketAddress, connection.getRoute().getSocketAddress().getAddress());
    assertEquals(socketPort, connection.getRoute().getSocketAddress().getPort());
    assertEquals(modernTls, connection.getRoute().isModernTls());
  }

  private static InetAddress[] makeFakeAddresses(int prefix, int count) {
    try {
      InetAddress[] result = new InetAddress[count];
      for (int i = 0; i < count; i++) {
        result[i] =
            InetAddress.getByAddress(new byte[] { (byte) prefix, (byte) 0, (byte) 0, (byte) i });
      }
      return result;
    } catch (UnknownHostException e) {
      throw new AssertionError();
    }
  }

  private static class FakeDns implements Dns {
    List<String> requestedHosts = new ArrayList<String>();
    InetAddress[] inetAddresses;

    @Override public InetAddress[] getAllByName(String host) throws UnknownHostException {
      requestedHosts.add(host);
      if (inetAddresses == null) throw new UnknownHostException();
      return inetAddresses;
    }

    public void assertRequests(String... expectedHosts) {
      assertEquals(Arrays.asList(expectedHosts), requestedHosts);
      requestedHosts.clear();
    }
  }

  private static class FakeProxySelector extends ProxySelector {
    List<URI> requestedUris = new ArrayList<URI>();
    List<Proxy> proxies = new ArrayList<Proxy>();
    List<String> failures = new ArrayList<String>();

    @Override public List<Proxy> select(URI uri) {
      requestedUris.add(uri);
      return proxies;
    }

    public void assertRequests(URI... expectedUris) {
      assertEquals(Arrays.asList(expectedUris), requestedUris);
      requestedUris.clear();
    }

    @Override public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
      InetSocketAddress socketAddress = (InetSocketAddress) sa;
      failures.add(
          String.format("%s %s:%d %s", uri, socketAddress.getHostName(), socketAddress.getPort(),
              ioe.getMessage()));
    }
  }
}


text:
package com.jayantkrish.jklol.ccg;

import com.jayantkrish.jklol.ccg.chart.ChartEntry;

/**
 * Stack state of a shift-reduce CCG parser.
 *
 * @author jayantk
 */
public class ShiftReduceStack {
  public final int spanStart;
  public final int spanEnd;
  public final int chartEntryIndex;
  public final ChartEntry entry;
  public final double entryProb;
  public final boolean includesRootProb;

  public final ShiftReduceStack previous;

  public final int size;
  public final double totalProb;

  public ShiftReduceStack(int spanStart, int spanEnd, int chartEntryIndex, ChartEntry entry,
      double entryProb, boolean includesRootProb, ShiftReduceStack previous) {
    this.spanStart = spanStart;
    this.spanEnd = spanEnd;
    this.chartEntryIndex = chartEntryIndex;
    this.entry = entry;
    this.entryProb = entryProb;
    this.includesRootProb = includesRootProb;

    if (previous == null) {
      this.size = 0;
      this.totalProb = entryProb;
    } else {
      this.size = 1 + previous.size;
      this.totalProb = previous.totalProb * entryProb;
    }

    this.previous = previous;
  }

  public static ShiftReduceStack empty() {
    return new ShiftReduceStack(-1, -1, -1, null, 1.0, false, null);
  }

  public ShiftReduceStack push(int spanStart, int spanEnd, int chartEntryIndex, ChartEntry entry,
      double prob, boolean includesRootProb) {
    return new ShiftReduceStack(spanStart, spanEnd, chartEntryIndex, entry, prob,
        includesRootProb, this);
  }

  @Override
  public String toString() {
    String prevString = previous == null ? "" : previous.toString();
    return spanStart + "," + spanEnd + " : " + prevString;
  }
}