001: // Copyright 2006 The Apache Software Foundation
002: //
003: // Licensed under the Apache License, Version 2.0 (the "License");
004: // you may not use this file except in compliance with the License.
005: // You may obtain a copy of the License at
006: //
007: // http://www.apache.org/licenses/LICENSE-2.0
008: //
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014:
015: package org.apache.tapestry.ioc.internal.util;
016:
017: import static org.apache.tapestry.ioc.internal.util.Defense.notBlank;
018: import static org.apache.tapestry.ioc.internal.util.Defense.notNull;
019:
020: import java.net.URL;
021: import java.util.Locale;
022:
023: import org.apache.tapestry.ioc.Resource;
024:
025: /**
026: * Abstract implementation of {@link Resource}. Subclasses must implement the abstract methods
027: * {@link Resource#toURL()} and {@link #newResource(String)} as well as toString(), hashCode() and
028: * equals().
029: */
030: public abstract class AbstractResource implements Resource {
031: private final String _path;
032:
033: protected AbstractResource(String path) {
034: notNull(path, "path");
035: _path = path;
036:
037: }
038:
039: public final String getPath() {
040: return _path;
041: }
042:
043: public final String getFile() {
044: int slashx = _path.lastIndexOf('/');
045:
046: return _path.substring(slashx + 1);
047: }
048:
049: public final String getFolder() {
050: int slashx = _path.lastIndexOf('/');
051:
052: return (slashx < 0) ? "" : _path.substring(0, slashx);
053: }
054:
055: public final Resource forFile(String relativePath) {
056: Defense.notNull(relativePath, "relativePath");
057:
058: StringBuilder builder = new StringBuilder(getFolder());
059:
060: for (String term : relativePath.split("/")) {
061: // This will occur if the relative path contains sequential slashes
062:
063: if (term.equals(""))
064: continue;
065:
066: if (term.equals("."))
067: continue;
068:
069: if (term.equals("..")) {
070: int slashx = builder.lastIndexOf("/");
071:
072: // TODO: slashx < 0 (i.e., no slash)
073:
074: // Trim path to content before the slash
075:
076: builder.setLength(slashx);
077: continue;
078: }
079:
080: // TODO: term blank or otherwise invalid?
081: // TODO: final term should not be "." or "..", or for that matter, the
082: // name of a folder, since a Resource should be a file within
083: // a folder.
084:
085: if (builder.length() > 0)
086: builder.append("/");
087:
088: builder.append(term);
089: }
090:
091: return createResource(builder.toString());
092: }
093:
094: public final Resource forLocale(Locale locale) {
095: for (String path : new LocalizedNameGenerator(_path, locale)) {
096: Resource potential = createResource(path);
097:
098: URL url = potential.toURL();
099:
100: if (url != null)
101: return potential;
102: }
103:
104: return null;
105: }
106:
107: public final Resource withExtension(String extension) {
108: notBlank(extension, "extension");
109:
110: int dotx = _path.lastIndexOf('.');
111:
112: if (dotx < 0)
113: return createResource(_path + "." + extension);
114:
115: return createResource(_path.substring(0, dotx + 1) + extension);
116: }
117:
118: /**
119: * Creates a new resource, unless the path matches the current Resource's path (in which case,
120: * this resource is returned).
121: */
122: private Resource createResource(String path) {
123: if (_path.equals(path))
124: return this ;
125:
126: return newResource(path);
127: }
128:
129: /** Factory method provided by subclasses. */
130: protected abstract Resource newResource(String path);
131: }
|