| /** |
| * Copyright 2010 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: sligocki@google.com (Shawn Ligocki) |
| // |
| // Output resources are created by a ResourceManager. They must be able to |
| // write contents and return their url (so that it can be href'd on a page). |
| |
| #ifndef NET_INSTAWEB_REWRITER_PUBLIC_OUTPUT_RESOURCE_H_ |
| #define NET_INSTAWEB_REWRITER_PUBLIC_OUTPUT_RESOURCE_H_ |
| |
| #include "base/basictypes.h" |
| #include "base/scoped_ptr.h" |
| #include "net/instaweb/util/public/file_system.h" |
| #include "net/instaweb/util/public/file_writer.h" |
| #include <string> |
| #include "net/instaweb/util/public/string_util.h" |
| #include "net/instaweb/rewriter/public/resource.h" |
| #include "net/instaweb/rewriter/public/resource_namer.h" |
| |
| namespace net_instaweb { |
| |
| class FilenameEncoder; |
| class MessageHandler; |
| |
| class OutputResource : public Resource { |
| public: |
| // Construct an OutputResource. For the moment, we pass in type redundantly |
| // even though full_name embeds an extension. This reflects current code |
| // structure rather than a principled stand on anything. |
| // TODO(jmaessen): remove redundancy. |
| OutputResource(ResourceManager* manager, |
| const StringPiece& resolved_base, |
| const ResourceNamer& resource_id, |
| const ContentType* type); |
| ~OutputResource(); |
| |
| virtual bool ReadIfCached(MessageHandler* message_handler); |
| virtual std::string url() const; |
| |
| // output-specific |
| const std::string& resolved_base() const { return resolved_base_; } |
| const ResourceNamer& full_name() const { return full_name_; } |
| StringPiece name() const { return full_name_.name(); } |
| std::string filename() const; |
| StringPiece suffix() const; |
| StringPiece filter_prefix() const { return full_name_.id(); } |
| |
| // In a scalable installation where the sprites must be kept in a |
| // database, we cannot serve HTML that references new resources |
| // that have not been committed yet, and committing to a database |
| // may take too long to block on the HTML rewrite. So we will want |
| // to refactor this to check to see whether the desired resource is |
| // already known. For now we'll assume we can commit to serving the |
| // resource during the HTML rewriter. |
| bool IsWritten() const; |
| |
| // Sets the suffix for an output resource. This must be called prior |
| // to Write if the content_type ctor arg was NULL. This can happen if |
| // we are managing a resource whose content-type is not known to us. |
| // CacheExtender is currently the only place where we need this. |
| void set_suffix(const StringPiece& ext); |
| |
| // Sets the type of the output resource, and thus also its suffix. |
| virtual void SetType(const ContentType* type); |
| |
| // Determines whether the output resource has a valid URL. If so, |
| // we don't need to actually load the output-resource content from |
| // cache during the Rewriting process -- we can immediately rewrite |
| // the href to it. |
| // |
| // Note that when serving content, we must actually load it, but |
| // when rewriting it we can, in some cases, exploit a URL swap. |
| bool HasValidUrl() const { return has_hash(); } |
| |
| // Resources rewritten via a UrlPartnership will have a resolved |
| // base to use in lieu of the legacy UrlPrefix held by the resource |
| // manager. |
| void set_resolved_base(const StringPiece& base) { |
| base.CopyToString(&resolved_base_); |
| } |
| |
| private: |
| friend class ResourceManager; |
| friend class ResourceManagerTestingPeer; |
| class OutputWriter { |
| public: |
| // file may be null if we shouldn't write to the filesystem. |
| OutputWriter(FileSystem::OutputFile* file, HTTPValue* http_value) |
| : http_value_(http_value) { |
| if (file != NULL) { |
| file_writer_.reset(new FileWriter(file)); |
| } else { |
| file_writer_.reset(NULL); |
| } |
| } |
| |
| // Adds the given data to our http_value, and, if |
| // non-null, our file. |
| bool Write(const StringPiece& data, MessageHandler* handler); |
| private: |
| scoped_ptr<FileWriter> file_writer_; |
| HTTPValue* http_value_; |
| }; |
| |
| void SetHash(const StringPiece& hash); |
| StringPiece hash() const { return full_name_.hash(); } |
| bool has_hash() const { return !hash().empty(); } |
| void set_written(bool written) { writing_complete_ = true; } |
| void set_generated(bool x) { generated_ = x; } |
| bool generated() const { return generated_; } |
| OutputWriter* BeginWrite(MessageHandler* message_handler); |
| bool EndWrite(OutputWriter* writer, MessageHandler* message_handler); |
| |
| std::string TempPrefix() const; |
| |
| FileSystem::OutputFile* output_file_; |
| bool writing_complete_; |
| |
| // Generated via ResourceManager::CreateGeneratedOutputResource, |
| // meaning that it does not have a name that is derived from an |
| // input URL. We must regenerate it every time, but the output name |
| // will be distinct because it's based on the hash of the content. |
| bool generated_; |
| |
| // If this output url was created via a partnership then this field |
| // will be non-empty, and we will not need to use the resource manager's |
| // prefix. |
| std::string resolved_base_; |
| ResourceNamer full_name_; |
| |
| DISALLOW_COPY_AND_ASSIGN(OutputResource); |
| }; |
| |
| } // namespace net_instaweb |
| |
| #endif // NET_INSTAWEB_REWRITER_PUBLIC_OUTPUT_RESOURCE_H_ |