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

#ifndef PAGESPEED_APACHE_APACHE_SERVER_CONTEXT_H_
#define PAGESPEED_APACHE_APACHE_SERVER_CONTEXT_H_

#include "net/instaweb/http/public/request_context.h"
#include "net/instaweb/rewriter/public/rewrite_stats.h"
#include "pagespeed/apache/apache_config.h"
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/message_handler.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/system/system_server_context.h"

struct request_rec;
struct server_rec;

namespace net_instaweb {

class ApacheRewriteDriverFactory;
class ApacheRequestContext;
class ProxyFetchFactory;
class RewriteDriverPool;
class RewriteDriver;
class Statistics;
class Variable;

// Creates an Apache-specific ServerContext.  This differs from base class
// that it incorporates by adding per-VirtualHost configuration, including:
//    - file-cache path & limits
//    - default RewriteOptions.
// Additionally, there are startup semantics for apache's prefork model
// that require a phased initialization.
class ApacheServerContext : public SystemServerContext {
 public:
  ApacheServerContext(ApacheRewriteDriverFactory* factory,
                      server_rec* server,
                      const StringPiece& version);
  virtual ~ApacheServerContext();

  // This must be called for every statistics object in use before using this.
  static void InitStats(Statistics* statistics);

  ApacheRewriteDriverFactory* apache_factory() { return apache_factory_; }
  ApacheConfig* global_config();
  bool InitPath(const GoogleString& path);

  // These return configuration objects that hold settings from
  // <ModPagespeedIf spdy> and <ModPagespeedIf !spdy> sections of configuration.
  // They initialize lazily, so are not thread-safe; however they are only
  // meant to be used during configuration parsing. These methods should be
  // called only if there is actually a need to put something in them, since
  // otherwise we may end up constructing separate SPDY vs. non-SPDY
  // configurations needlessly.
  ApacheConfig* SpdyConfigOverlay();
  ApacheConfig* NonSpdyConfigOverlay();

  // These return true if the given overlays were constructed (in response
  // to having something in config files to put in them).
  bool has_spdy_config_overlay() const {
    return spdy_config_overlay_.get() != NULL;
  }

  bool has_non_spdy_config_overlay() const {
    return non_spdy_config_overlay_.get() != NULL;
  }

  // These two take ownership of their parameters.
  void set_spdy_config_overlay(ApacheConfig* x) {
    spdy_config_overlay_.reset(x);
  }

  void set_non_spdy_config_overlay(ApacheConfig* x) {
    non_spdy_config_overlay_.reset(x);
  }

  // Returns special configuration that should be used for SPDY sessions
  // instead of global_config(). Returns NULL if global_config() should be
  // used instead.
  virtual const ApacheConfig* SpdyGlobalConfig() const {
    return spdy_specific_config_.get();
  }

  // Pool to pass to NewRewriteDriverFromPool to get a RewriteDriver configured
  // with SPDY-specific options. May be NULL in case there is no spdy-specific
  // configuration.
  RewriteDriverPool* spdy_driver_pool() { return spdy_driver_pool_; }

  // This should be called after all configuration parsing is done to collapse
  // configuration inside the config overlays into actual ApacheConfig objects.
  // It will also compute signatures when done.
  virtual void CollapseConfigOverlaysAndComputeSignatures();

  // Called on notification from Apache on child exit. Returns true
  // if this is the last ServerContext that exists.
  bool PoolDestroyed();

  const server_rec* server() const { return server_rec_; }

  virtual RewriteDriverPool* SelectDriverPool(bool using_spdy);

  // Hook for implementations to support fetching directly from the spdy module.
  virtual void MaybeApplySpdySessionFetcher(const RequestContextPtr& request,
                                            RewriteDriver* driver);

  ProxyFetchFactory* proxy_fetch_factory() {
    return proxy_fetch_factory_.get();
  }

  void InitProxyFetchFactory();

  // We do not proxy external HTML from mod_pagespeed in Apache using the
  // ProxyFetch flow.  Currently we must rely on a separate module to
  // let mod_pagespeed behave as an origin fetcher.
  virtual bool ProxiesHtml() const { return false; }

  // Creates a request context which is suitable for resolving
  // options, but is not yet suitable for establishing a context from
  // which to do fetches.  Establishing that context is slightly
  // expensive so we want to only do that in request-paths that can
  // lead to spdy fetches.
  //
  // To enable a rewrite context for fetching, call
  //   apache_request_context->SetupSpdyConnectionIfNeeded(request);
  // after the object is context is constructed.
  ApacheRequestContext* NewApacheRequestContext(request_rec* request);

  // Reports an error status to the HTTP resource request, and logs
  // the error as a Warning to the log file, and bumps a stat as
  // needed.
  void ReportResourceNotFound(StringPiece message, request_rec* request) {
    ReportNotFoundHelper(kWarning, message, request,
                         rewrite_stats()->resource_404_count());
  }

  // Reports an error status to the HTTP statistics request, and logs
  // the error as a Warning to the log file, and bumps a stat as
  // needed.
  void ReportStatisticsNotFound(StringPiece message, request_rec* request) {
    ReportNotFoundHelper(kWarning, message, request, statistics_404_count());
  }

  // Reports an error status to the HTTP slurp request, and logs
  // the error as a Warning to the log file, and bumps a stat as
  // needed.
  void ReportSlurpNotFound(StringPiece message, request_rec* request) {
    ReportNotFoundHelper(kInfo, message, request,
                         rewrite_stats()->slurp_404_count());
  }

  virtual GoogleString FormatOption(StringPiece option_name, StringPiece args);

 private:
  virtual bool UpdateCacheFlushTimestampMs(int64 timestamp_ms);

  void ReportNotFoundHelper(MessageType message_type,
                            StringPiece url,
                            request_rec* request,
                            Variable* error_count);

  ApacheRewriteDriverFactory* apache_factory_;
  server_rec* server_rec_;
  GoogleString version_;

  // May be NULL. Constructed once we see things in config files that should
  // be stored in these.
  scoped_ptr<ApacheConfig> spdy_config_overlay_;
  scoped_ptr<ApacheConfig> non_spdy_config_overlay_;

  // May be NULL if we don't have any special settings for when using SPDY.
  scoped_ptr<ApacheConfig> spdy_specific_config_;

  // Owned by ServerContext via a call to ManageRewriteDriverPool.
  // May be NULL if we don't have a spdy-specific configuration.
  RewriteDriverPool* spdy_driver_pool_;

  scoped_ptr<ProxyFetchFactory> proxy_fetch_factory_;

  DISALLOW_COPY_AND_ASSIGN(ApacheServerContext);
};

}  // namespace net_instaweb

#endif  // PAGESPEED_APACHE_APACHE_SERVER_CONTEXT_H_
