org.jclouds.demo.tweetstore.config.SpringServletConfig.java Source code

Java tutorial

Introduction

Here is the source code for org.jclouds.demo.tweetstore.config.SpringServletConfig.java

Source

/**
 *
 * Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
 *
 * ====================================================================
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ====================================================================
 */
package org.jclouds.demo.tweetstore.config;

import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.demo.tweetstore.reference.TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;

import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.BlobStoreContextFactory;
import org.jclouds.demo.tweetstore.controller.AddTweetsController;
import org.jclouds.demo.tweetstore.controller.StoreTweetsController;
import org.jclouds.demo.tweetstore.functions.ServiceToStoredTweetStatuses;
import org.jclouds.gae.config.GoogleAppEngineConfigurationModule;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.ServletConfigAware;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.SimpleServletHandlerAdapter;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;

import twitter4j.Twitter;
import twitter4j.TwitterFactory;
import twitter4j.conf.ConfigurationBuilder;

import com.google.appengine.api.taskqueue.Queue;
import com.google.appengine.api.taskqueue.QueueFactory;
import com.google.appengine.api.taskqueue.TaskOptions.Builder;
import com.google.appengine.api.taskqueue.TaskOptions.Method;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.io.Closeables;
import com.google.inject.Module;

/**
 * Creates servlets (using resources from the {@link SpringAppConfig}) and mappings.
 * 
 * @author Andrew Phillips
 * @see SpringAppConfig
 */
@Configuration
public class SpringServletConfig extends LoggingConfig implements ServletConfigAware {
    public static final String PROPERTY_BLOBSTORE_CONTEXTS = "blobstore.contexts";

    private ServletConfig servletConfig;

    private Map<String, BlobStoreContext> providerTypeToBlobStoreMap;
    private Twitter twitterClient;
    private String container;

    @PostConstruct
    public void initialize() throws IOException {
        BlobStoreContextFactory blobStoreContextFactory = new BlobStoreContextFactory();

        Properties props = loadJCloudsProperties();
        logger.trace("About to initialize members.");

        Module googleModule = new GoogleAppEngineConfigurationModule();
        Set<Module> modules = ImmutableSet.<Module>of(googleModule);
        // shared across all blobstores and used to retrieve tweets
        try {
            twitter4j.conf.Configuration twitterConf = new ConfigurationBuilder()
                    .setUser(props.getProperty("twitter.identity"))
                    .setPassword(props.getProperty("twitter.credential")).build();
            twitterClient = new TwitterFactory(twitterConf).getInstance();
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException(
                    "properties for twitter not configured properly in " + props.toString(), e);
        }
        // common namespace for storing tweets
        container = checkNotNull(props.getProperty(PROPERTY_TWEETSTORE_CONTAINER), PROPERTY_TWEETSTORE_CONTAINER);

        // instantiate and store references to all blobstores by provider name
        providerTypeToBlobStoreMap = Maps.newHashMap();
        for (String hint : Splitter.on(',')
                .split(checkNotNull(props.getProperty(PROPERTY_BLOBSTORE_CONTEXTS), PROPERTY_BLOBSTORE_CONTEXTS))) {
            providerTypeToBlobStoreMap.put(hint, blobStoreContextFactory.createContext(hint, modules, props));
        }

        // get a queue for submitting store tweet requests
        Queue queue = QueueFactory.getQueue("twitter");
        // submit a job to store tweets for each configured blobstore
        for (String name : providerTypeToBlobStoreMap.keySet()) {
            queue.add(withUrl("/store/do").header("context", name).method(Method.GET));
        }
        logger.trace("Members initialized. Twitter: '%s', container: '%s', provider types: '%s'", twitterClient,
                container, providerTypeToBlobStoreMap.keySet());
    }

    private Properties loadJCloudsProperties() {
        logger.trace("About to read properties from '%s'", "/WEB-INF/jclouds.properties");
        Properties props = new Properties();
        InputStream input = servletConfig.getServletContext().getResourceAsStream("/WEB-INF/jclouds.properties");
        try {
            props.load(input);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            Closeables.closeQuietly(input);
        }
        logger.trace("Properties successfully read.");
        return props;
    }

    @Bean
    public StoreTweetsController storeTweetsController() {
        StoreTweetsController controller = new StoreTweetsController(providerTypeToBlobStoreMap, container,
                twitterClient);
        injectServletConfig(controller);
        return controller;
    }

    @Bean
    public AddTweetsController addTweetsController() {
        AddTweetsController controller = new AddTweetsController(providerTypeToBlobStoreMap,
                serviceToStoredTweetStatuses());
        injectServletConfig(controller);
        return controller;
    }

    private void injectServletConfig(Servlet servlet) {
        logger.trace("About to inject servlet config '%s'", servletConfig);
        try {
            servlet.init(checkNotNull(servletConfig));
        } catch (ServletException exception) {
            throw new BeanCreationException("Unable to instantiate " + servlet, exception);
        }
        logger.trace("Successfully injected servlet config.");
    }

    @Bean
    ServiceToStoredTweetStatuses serviceToStoredTweetStatuses() {
        return new ServiceToStoredTweetStatuses(providerTypeToBlobStoreMap, container);
    }

    @Bean
    public HandlerMapping handlerMapping() {
        SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
        Map<String, Object> urlMap = Maps.newHashMapWithExpectedSize(2);
        urlMap.put("/store/*", storeTweetsController());
        urlMap.put("/tweets/*", addTweetsController());
        mapping.setUrlMap(urlMap);
        /*
         * "/store" and "/tweets" are part of the servlet mapping and thus stripped by the mapping if
         * using default settings.
         */
        mapping.setAlwaysUseFullPath(true);
        return mapping;
    }

    @Bean
    public HandlerAdapter servletHandlerAdapter() {
        return new SimpleServletHandlerAdapter();
    }

    @PreDestroy
    public void destroy() throws Exception {
        logger.trace("About to close contexts.");
        for (BlobStoreContext context : providerTypeToBlobStoreMap.values()) {
            context.close();
        }
        logger.trace("Contexts closed.");
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.springframework.web.context.ServletConfigAware#setServletConfig(javax.servlet.ServletConfig
     * )
     */
    @Override
    public void setServletConfig(ServletConfig servletConfig) {
        this.servletConfig = servletConfig;
    }
}