Chromium Code Reviews| 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: |