From: SVN c. m. f. t. SWORD-A. p. <swo...@li...> - 2012-01-15 16:30:34
|
Revision: 450 http://sword-app.svn.sourceforge.net/sword-app/?rev=450&view=rev Author: richard-jones Date: 2012-01-15 16:30:27 +0000 (Sun, 15 Jan 2012) Log Message: ----------- separate html interface from web layer in both web.py and pylons implementations Modified Paths: -------------- sss/branches/sss-2/sss/__init__.py sss/branches/sss-2/sss/config.py sss/branches/sss-2/sss/core.py sss/branches/sss-2/sss/pylons_sword_controller.py sss/branches/sss-2/sss/repository.py sss/branches/sss-2/sss/webpy.py Modified: sss/branches/sss-2/sss/__init__.py =================================================================== --- sss/branches/sss-2/sss/__init__.py 2012-01-14 13:34:07 UTC (rev 449) +++ sss/branches/sss-2/sss/__init__.py 2012-01-15 16:30:27 UTC (rev 450) @@ -1,6 +1,6 @@ from info import __version__, __author__, __license__ -from core import Auth, AuthException, Authenticator, DeleteRequest, DeleteResponse, DepositRequest, DepositResponse, EntryDocument, SDCollection, SWORDRequest, ServiceDocument, Statement, SwordError, SwordServer +from core import Auth, AuthException, Authenticator, DeleteRequest, DeleteResponse, DepositRequest, DepositResponse, EntryDocument, SDCollection, SWORDRequest, ServiceDocument, Statement, SwordError, SwordServer, WebUI from config import Configuration, SSS_CONFIG_FILE from spec import Errors, HttpHeaders Modified: sss/branches/sss-2/sss/config.py =================================================================== --- sss/branches/sss-2/sss/config.py 2012-01-14 13:34:07 UTC (rev 449) +++ sss/branches/sss-2/sss/config.py 2012-01-15 16:30:27 UTC (rev 450) @@ -119,7 +119,8 @@ }, "sword_server" : "sss.repository.SSS", - "authenticator" : "sss.repository.SSSAuthenticator" + "authenticator" : "sss.repository.SSSAuthenticator", + "webui" : "sss.repository.WebInterface" } """ @@ -144,6 +145,9 @@ def get_authenticator_implementation(self): return self._get_class(self.authenticator) + + def get_webui_implementation(self): + return self._get_class(self.webui) def get_container_formats(self): default_params = self._get_accept_params(self.container_format_default) @@ -213,6 +217,9 @@ return self._load_class(modpath, classname) else: raise e + except AttributeError as e: + ssslog.debug("Tried and failed to load " + classname + " from " + modpath) + raise e def _load_json(self): if not os.path.isfile(self.SSS_CONFIG_FILE): Modified: sss/branches/sss-2/sss/core.py =================================================================== --- sss/branches/sss-2/sss/core.py 2012-01-14 13:34:07 UTC (rev 449) +++ sss/branches/sss-2/sss/core.py 2012-01-15 16:30:27 UTC (rev 450) @@ -856,3 +856,9 @@ return rdf +class WebUI(object): + def __init__(self, config): + self.config = config + + def get(self, path=None): + return Modified: sss/branches/sss-2/sss/pylons_sword_controller.py =================================================================== --- sss/branches/sss-2/sss/pylons_sword_controller.py 2012-01-14 13:34:07 UTC (rev 449) +++ sss/branches/sss-2/sss/pylons_sword_controller.py 2012-01-15 16:30:27 UTC (rev 450) @@ -7,8 +7,8 @@ from core import Auth, SWORDSpec, SwordError, AuthException, DepositRequest, DeleteRequest from negotiator import ContentNegotiator, AcceptParameters, ContentType from spec import Errors, HttpHeaders, ValidationException -from webui import HomePage, CollectionPage, ItemPage + import logging ssslog = logging.getLogger(__name__) @@ -17,6 +17,7 @@ config = Configuration() Authenticator = config.get_authenticator_implementation() SwordServer = config.get_server_implementation() +WebInterface = config.get_webui_implementation() __controller__ = "SwordController" @@ -336,7 +337,6 @@ abort(405, "Method Not Allowed") return - def part(self, path=None): http_method = request.environ['REQUEST_METHOD'] if http_method == "GET": @@ -819,16 +819,8 @@ return def _GET_webui(self, path=None): - if path is not None: - if path.find("/") >= 0: - ip = ItemPage(config) - return ip.get_item_page(path) - else: - cp = CollectionPage(config) - return cp.get_collection_page(path) - else: - hp = HomePage(config) - return hp.get_home_page() + w = WebInterface(config) + return w.get(path) def _GET_part(self, path): ss = SwordServer(config, None) Modified: sss/branches/sss-2/sss/repository.py =================================================================== --- sss/branches/sss-2/sss/repository.py 2012-01-14 13:34:07 UTC (rev 449) +++ sss/branches/sss-2/sss/repository.py 2012-01-15 16:30:27 UTC (rev 450) @@ -1,5 +1,5 @@ import os, hashlib, uuid, urllib -from core import Statement, DepositResponse, MediaResourceResponse, DeleteResponse, SWORDSpec, Auth, AuthException, SwordError, ServiceDocument, SDCollection, EntryDocument, Authenticator, SwordServer +from core import Statement, DepositResponse, MediaResourceResponse, DeleteResponse, SWORDSpec, Auth, AuthException, SwordError, ServiceDocument, SDCollection, EntryDocument, Authenticator, SwordServer, WebUI from spec import Namespaces, Errors from lxml import etree from datetime import datetime @@ -10,6 +10,19 @@ from sss_logging import logging ssslog = logging.getLogger(__name__) +class WebInterface(WebUI): + def get(self, path=None): + if path is not None: + if path.find("/") >= 0: + ip = ItemPage(self.config) + return ip.get_item_page(path) + else: + cp = CollectionPage(self.config) + return cp.get_collection_page(path) + else: + hp = HomePage(self.config) + return hp.get_home_page() + class SSSAuthenticator(Authenticator): def __init__(self, config): Authenticator.__init__(self, config) @@ -1111,4 +1124,106 @@ cfiles = [f for f in os.listdir(odir) if not f.startswith("sss_") and not f in exclude] return cfiles +# Basic Web Interface +####################################################################### +class WebPage(object): + def _wrap_html(self, title, frag, head_frag=None): + return "<html><head><title>" + title + "</title>" + head_frag + "</head><body>" + frag + "</body></html>" + +class HomePage(WebPage): + """ + Welcome / home page + """ + def __init__(self, config): + self.config = config + self.dao = DAO(self.config) + self.um = URIManager(config) + + def get_home_page(self): + frag = "<h1>Simple SWORDv2 Server</h1>" + frag += "<p><strong>Service Document (SD-IRI)</strong>: <a href=\"" + self.config.base_url + "sd-uri\">" + self.config.base_url + "sd-uri</a></p>" + frag += "<p>If prompted, use the username <strong>" + self.config.user + "</strong> and the password <strong>" + self.config.password + "</strong></p>" + frag += "<p>The On-Behalf-Of user to use is <strong>" + self.config.obo + "</strong></p>" + + # list the collections + frag += "<h2>Collections</h2><ul>" + for col in self.dao.get_collection_names(): + frag += "<li><a href=\"" + self.um.html_url(col) + "\">" + col + "</a></li>" + frag += "</ul>" + + head_frag = "<link rel=\"http://purl.org/net/sword/discovery/service-document\" href=\"" + self.config.base_url + "sd-uri\"/>" + + return self._wrap_html("Simple SWORDv2 Server", frag, head_frag) + +class CollectionPage(WebPage): + def __init__(self, config): + self.config = config + self.dao = DAO(config) + self.um = URIManager(config) + + def get_collection_page(self, id): + frag = "<h1>Collection: " + id + "</h1>" + + # list all of the containers in the collection + cpath = self.dao.get_store_path(id) + containers = os.listdir(cpath) + frag += "<h2>Containers</h2><ul>" + for container in containers: + frag += "<li><a href=\"" + self.um.html_url(id, container) + "\">" + container + "</a></li>" + frag += "</ul>" + + head_frag = "<link rel=\"http://purl.org/net/sword/terms/deposit\" href=\"" + self.um.col_uri(id) + "\"/>" + + return self._wrap_html("Collection: " + id, frag, head_frag) + +class ItemPage(WebPage): + def __init__(self, config): + self.config = config + self.dao = DAO(config) + self.um = URIManager(config) + + def get_item_page(self, oid): + collection, id = self.um.interpret_oid(oid) + statement = self.dao.load_statement(collection, id) + metadata = self.dao.get_metadata(collection, id) + + state_frag = self._get_state_frag(statement) + md_frag = self._layout_metadata(metadata) + file_frag = self._layout_files(statement) + + frag = "<h1>Item: " + id + "</h1>" + frag += "<strong>State</strong>: " + state_frag + frag += self._layout_sections(md_frag, file_frag) + + head_frag = "<link rel=\"http://purl.org/net/sword/terms/edit\" href=\"" + self.um.edit_uri(collection, id) + "\"/>" + head_frag += "<link rel=\"http://purl.org/net/sword/terms/statement\" href=\"" + self.um.state_uri(collection, id, "atom") + "\"/>" + head_frag += "<link rel=\"http://purl.org/net/sword/terms/statement\" href=\"" + self.um.state_uri(collection, id, "ore") + "\"/>" + + return self._wrap_html("Item: " + id, frag, head_frag) + + def _layout_metadata(self, metadata): + frag = "<h2>Metadata</h2>" + for key, vals in metadata.iteritems(): + frag += "<strong>" + key + "</strong>: " + ", ".join(vals) + "<br/>" + if len(metadata) == 0: + frag += "No metadata associated with this item" + return frag + + def _layout_files(self, statement): + frag = "<h2>Files</h2>" + frag += "<table border=\"1\"><tr><th>URI</th><th>deposited on</th><th>format</th><th>deposited by</th><th>on behalf of</th></tr>" + for uri, deposit_time, format, by, obo in statement.original_deposits: + frag += "<tr><td><a href=\"" + uri + "\">" + uri + "</a></td><td>" + str(deposit_time) + "</td><td>" + format + frag += "</td><td>" + by + "</td><td>" + str(obo) + "</td></tr>" + frag += "</table>" + return frag + + def _get_state_frag(self, statement): + if statement.in_progress: + return statement.in_progress_uri + else: + return statement.archived_uri + + def _layout_sections(self, metadata, files): + return "<table border=\"0\"><tr><td valign=\"top\">" + metadata + "</td><td valign=\"top\">" + files + "</td></tr></table>" Modified: sss/branches/sss-2/sss/webpy.py =================================================================== --- sss/branches/sss-2/sss/webpy.py 2012-01-14 13:34:07 UTC (rev 449) +++ sss/branches/sss-2/sss/webpy.py 2012-01-15 16:30:27 UTC (rev 450) @@ -2,7 +2,6 @@ from web.wsgiserver import CherryPyWSGIServer from core import Auth, SWORDSpec, SwordError, AuthException, DepositRequest, DeleteRequest from negotiator import ContentNegotiator, AcceptParameters, ContentType -from webui import HomePage, CollectionPage, ItemPage from spec import Errors, HttpHeaders, ValidationException from sss_logging import logging @@ -13,6 +12,7 @@ config = Configuration() Authenticator = config.get_authenticator_implementation() SwordServer = config.get_server_implementation() +WebInterface = config.get_webui_implementation() # Whether to run using SSL. This uses a default self-signed certificate. Change the paths to # use an alternative set of keys @@ -734,16 +734,8 @@ Class to provide a basic web interface to the store for convenience """ def GET(self, path=None): - if path is not None: - if path.find("/") >= 0: - ip = ItemPage(config) - return ip.get_item_page(path) - else: - cp = CollectionPage(config) - return cp.get_collection_page(path) - else: - hp = HomePage(config) - return hp.get_home_page() + w = WebInterface(config) + return w.get(path) class Part(SwordHttpHandler): """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |