Index: chrome/common/extensions/docs/server2/server_instance.py |
diff --git a/chrome/common/extensions/docs/server2/server_instance.py b/chrome/common/extensions/docs/server2/server_instance.py |
index c3ecabc664f5f91dd611c664044a52076a85fb32..81d1f68ec29a3c2a54366028560c2207ead61ea3 100644 |
--- a/chrome/common/extensions/docs/server2/server_instance.py |
+++ b/chrome/common/extensions/docs/server2/server_instance.py |
@@ -6,48 +6,182 @@ from fnmatch import fnmatch |
import mimetypes |
import os |
+from api_data_source import APIDataSource |
+from api_list_data_source import APIListDataSource |
+from appengine_blobstore import AppEngineBlobstore |
+from appengine_url_fetcher import AppEngineUrlFetcher |
+from branch_utility import BranchUtility |
+from compiled_file_system import CompiledFileSystem |
+from example_zipper import ExampleZipper |
from file_system import FileNotFoundError |
-import compiled_file_system as compiled_fs |
- |
-STATIC_DIR_PREFIX = 'docs' |
-DOCS_PATH = 'docs' |
+from github_file_system import GithubFileSystem |
+from in_memory_object_store import InMemoryObjectStore |
+from intro_data_source import IntroDataSource |
+from local_file_system import LocalFileSystem |
+from caching_file_system import CachingFileSystem |
+from object_store_creator import ObjectStoreCreator |
+from path_canonicalizer import PathCanonicalizer |
+from reference_resolver import ReferenceResolver |
+from samples_data_source import SamplesDataSource |
+from sidenav_data_source import SidenavDataSource |
+from subversion_file_system import SubversionFileSystem |
+import svn_constants |
+from template_data_source import TemplateDataSource |
+from third_party.json_schema_compiler.model import UnixName |
+import url_constants |
def _IsBinaryMimetype(mimetype): |
return any(mimetype.startswith(prefix) |
for prefix in ['audio', 'image', 'video']) |
class ServerInstance(object): |
- """This class is used to hold a data source and fetcher for an instance of a |
- server. Each new branch will get its own ServerInstance. |
- """ |
- def __init__(self, |
- template_data_source_factory, |
- example_zipper, |
- cache_factory): |
- self._template_data_source_factory = template_data_source_factory |
- self._example_zipper = example_zipper |
- self._cache = cache_factory.Create(lambda _, x: x, compiled_fs.STATIC) |
+ '''Per-instance per-branch state. |
+ ''' |
+ _instances = {} |
+ |
+ branch_utility = None |
+ github_file_system = None |
+ |
+ @staticmethod |
+ def GetOrCreate(channel): |
+ branch_utility = ServerInstance.branch_utility |
cduvall
2013/04/08 07:09:24
is it necessary to assign ServerInstance.branch_ut
not at google - send to devlin
2013/04/08 12:21:21
Done. For GithubFileSystem too.
|
+ if branch_utility is None: |
+ branch_utility = BranchUtility(url_constants.OMAHA_PROXY_URL, |
+ AppEngineUrlFetcher()) |
+ ServerInstance.branch_utility = branch_utility |
+ |
+ branch = branch_utility.GetBranchNumberForChannelName(channel) |
+ |
+ # Use the branch as the key to |_instances| since the branch data is |
+ # predictable while the channel data (channels can swich branches) isn't. |
+ instance = ServerInstance._instances.get(branch) |
+ if instance is None: |
+ instance = ServerInstance._CreateForProduction(channel, branch) |
+ ServerInstance._instances[branch] = instance |
+ return instance |
+ |
+ @staticmethod |
+ def _CreateForProduction(channel, branch): |
+ if branch == 'trunk': |
+ svn_url = '/'.join((url_constants.SVN_TRUNK_URL, |
+ 'src', |
+ svn_constants.EXTENSIONS_PATH)) |
+ else: |
+ svn_url = '/'.join((url_constants.SVN_BRANCH_URL, |
+ branch, |
+ 'src', |
+ svn_constants.EXTENSIONS_PATH)) |
+ |
+ viewvc_url = svn_url.replace(url_constants.SVN_URL, |
+ url_constants.VIEWVC_URL) |
+ |
+ svn_file_system = CachingFileSystem( |
+ SubversionFileSystem(AppEngineUrlFetcher(svn_url), |
+ AppEngineUrlFetcher(viewvc_url))) |
+ |
+ github_file_system = ServerInstance.github_file_system |
+ if github_file_system is None: |
+ github_file_system = GithubFileSystem( |
+ AppEngineUrlFetcher(url_constants.GITHUB_URL), |
+ AppEngineBlobstore()) |
+ ServerInstance.github_file_system = github_file_system |
+ |
+ return ServerInstance(channel, svn_file_system, github_file_system) |
+ |
+ @staticmethod |
+ def CreateForTest(file_system): |
+ return ServerInstance('test', file_system, None) |
+ |
+ def __init__(self, channel, svn_file_system, github_file_system): |
+ self.svn_file_system = svn_file_system |
+ |
+ self.github_file_system = github_file_system |
+ |
+ self.compiled_fs_factory = CompiledFileSystem.Factory(svn_file_system) |
+ |
+ self.api_list_data_source_factory = APIListDataSource.Factory( |
+ self.compiled_fs_factory, |
+ svn_constants.API_PATH, |
+ svn_constants.PUBLIC_TEMPLATE_PATH) |
+ |
+ self.api_data_source_factory = APIDataSource.Factory( |
+ self.compiled_fs_factory, |
+ svn_constants.API_PATH) |
+ |
+ self.ref_resolver_factory = ReferenceResolver.Factory( |
+ self.api_data_source_factory, |
+ self.api_list_data_source_factory) |
+ |
+ self.api_data_source_factory.SetReferenceResolverFactory( |
+ self.ref_resolver_factory) |
+ |
+ self.samples_data_source_factory = SamplesDataSource.Factory( |
+ channel, |
+ self.svn_file_system, |
+ ServerInstance.github_file_system, |
+ self.ref_resolver_factory, |
+ svn_constants.EXAMPLES_PATH) |
+ |
+ self.api_data_source_factory.SetSamplesDataSourceFactory( |
+ self.samples_data_source_factory) |
+ |
+ self.intro_data_source_factory = IntroDataSource.Factory( |
+ self.compiled_fs_factory, |
+ self.ref_resolver_factory, |
+ [svn_constants.INTRO_PATH, svn_constants.ARTICLE_PATH]) |
+ |
+ self.sidenav_data_source_factory = SidenavDataSource.Factory( |
+ self.compiled_fs_factory, |
+ svn_constants.JSON_PATH) |
+ |
+ self.template_data_source_factory = TemplateDataSource.Factory( |
+ channel, |
+ self.api_data_source_factory, |
+ self.api_list_data_source_factory, |
+ self.intro_data_source_factory, |
+ self.samples_data_source_factory, |
+ self.sidenav_data_source_factory, |
+ self.compiled_fs_factory, |
+ self.ref_resolver_factory, |
+ svn_constants.PUBLIC_TEMPLATE_PATH, |
+ svn_constants.PRIVATE_TEMPLATE_PATH) |
+ |
+ self.example_zipper = ExampleZipper( |
+ self.svn_file_system, |
+ self.compiled_fs_factory, |
+ svn_constants.DOCS_PATH) |
+ |
+ self.path_canonicalizer = PathCanonicalizer( |
+ channel, |
+ self.compiled_fs_factory) |
+ |
+ self.content_cache = self.compiled_fs_factory.GetOrCreateIdentity() |
def _FetchStaticResource(self, path, response): |
"""Fetch a resource in the 'static' directory. |
""" |
mimetype = mimetypes.guess_type(path)[0] or 'text/plain' |
try: |
- result = self._cache.GetFromFile(STATIC_DIR_PREFIX + '/' + path, |
- binary=_IsBinaryMimetype(mimetype)) |
+ result = self.content_cache.GetFromFile( |
+ svn_constants.DOCS_PATH + '/' + path, |
+ binary=_IsBinaryMimetype(mimetype)) |
except FileNotFoundError: |
return None |
response.headers['content-type'] = mimetype |
return result |
def Get(self, path, request, response): |
- # TODO(cduvall): bundle up all the request-scoped data into a single object. |
- templates = self._template_data_source_factory.Create(request, path) |
+ templates = self.template_data_source_factory.Create(request, path) |
+ |
+ if path.rsplit('/', 1)[-1] in ('favicon.ico', 'robots.txt'): |
+ response.set_status(404) |
+ response.out.write(templates.Render('404')) |
+ return |
content = None |
if fnmatch(path, 'extensions/examples/*.zip'): |
try: |
- content = self._example_zipper.Create( |
+ content = self.example_zipper.Create( |
path[len('extensions/'):-len('.zip')]) |
response.headers['content-type'] = 'application/zip' |
except FileNotFoundError: |
@@ -55,8 +189,8 @@ class ServerInstance(object): |
elif path.startswith('extensions/examples/'): |
mimetype = mimetypes.guess_type(path)[0] or 'text/plain' |
try: |
- content = self._cache.GetFromFile( |
- '%s/%s' % (DOCS_PATH, path[len('extensions/'):]), |
+ content = self.content_cache.GetFromFile( |
+ '%s/%s' % (svn_constants.DOCS_PATH, path[len('extensions/'):]), |
binary=_IsBinaryMimetype(mimetype)) |
response.headers['content-type'] = 'text/plain' |
except FileNotFoundError: |