com.google.gxp.compiler.fs..svn.text-base.SourcePathFileSystem.svn-base Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of google-gxp Show documentation
Show all versions of google-gxp Show documentation
Google XML Pages (GXP) is a templating system used to generate XML/SGML markup (most often HTML).
The newest version!
/*
* Copyright (C) 2008 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.
*/
package com.google.gxp.compiler.fs;
import com.google.common.base.Function;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* A {@code FileSystem} wrapper that deals with the weird mappings between
* source paths and the output dir in GXP. As a wrapper {@code
* SourcePathFileSystem} necessarily have to deal with {@code Filenames} at two
* different ({@code FileSystem}) levels: the "wrapped" {@code FileSystem} and
* the {@code SourcePathFileSystem} itself.
*/
public class SourcePathFileSystem implements FileSystem {
// These maps contain the (bi-directional) mapping for source files.
private final BiMap spFsToWrappedFsSourceFileRef = HashBiMap.create();
private final BiMap wrappedFsToSpFsSourceFileRef =
spFsToWrappedFsSourceFileRef.inverse();
private final FileRef outDir;
private final FileSystem wrappedFs;
public SourcePathFileSystem(FileSystem wrappedFs,
Iterable sourcePath,
Iterable sourceFiles,
FileRef outDir) {
this.outDir = outDir;
this.wrappedFs = wrappedFs;
List sortedSourcePath = FILEREF_LENGTH_ORDERING.sortedCopy(sourcePath);
for (FileRef sourceFile : sourceFiles) {
FileRef baseDir = findBaseDir(sourceFile, sortedSourcePath);
if (baseDir == null) {
throw new IllegalArgumentException(sourceFile.toFilename() + " not in source path");
} else {
spFsToWrappedFsSourceFileRef.put(chop(baseDir, sourceFile), sourceFile);
}
}
}
private static FileRef findBaseDir(FileRef sourceFile, List sourcePath) {
for (FileRef sourceDir : sourcePath) {
if (sourceDir.isAncestorOf(sourceFile)) {
return sourceDir;
}
}
return null;
}
private static final Ordering FILEREF_LENGTH_ORDERING = new Ordering() {
public int compare(FileRef f1, FileRef f2) {
int len1 = f1.getName().length();
int len2 = f2.getName().length();
return (len1 > len2) ? -1 : (len1 == len2 ? 0 : 1);
}
private static final long serialVersionUID = 0;
};
private FileRef chop(FileRef ancestor, FileRef descendant) {
return new FileRef(store, descendant.getName().substring(ancestor.getName().length()));
}
private final FileStore store = new FileStore() {
public Charset getDefaultCharset() {
return SourcePathFileSystem.this.getDefaultCharset();
}
public URI toUri(FileRef fileRef) {
return toWrappedFsFileRef(fileRef, false).toUri();
}
public long getLastModified(FileRef fileRef) {
return toWrappedFsFileRef(fileRef, false).getLastModified();
}
public String toFilename(FileRef fileRef) {
return toWrappedFsFileRef(fileRef, false).toFilename();
}
public String toRelativeFilename(FileRef fileRef) {
return toWrappedFsFileRef(fileRef, false).toRelativeFilename();
}
public InputStream openInputStream(FileRef fileRef) throws IOException {
return toWrappedFsFileRef(fileRef, false).openInputStream();
}
public OutputStream openOutputStream(FileRef fileRef)
throws IOException {
FileRef wrappedFsFileRef = toWrappedFsFileRef(fileRef, true);
if (wrappedFsFileRef == null) {
throw new IOException("Attempted to open source file, "
+ fileRef.toFilename() + ", for writing.");
} else {
return wrappedFsFileRef.openOutputStream();
}
}
public boolean delete(FileRef fileRef) {
return toWrappedFsFileRef(fileRef, false).delete();
}
};
public FileRef getRoot() {
return new FileRef(store, "/");
}
public FileRef parseFilename(String filename) {
return FROM_WRAPPED_FS_FILEREF.apply(wrappedFs.parseFilename(filename));
}
public List parseFilenameList(String filenameList) {
return Lists.transform(wrappedFs.parseFilenameList(filenameList),
FROM_WRAPPED_FS_FILEREF);
}
public Charset getDefaultCharset() {
return wrappedFs.getDefaultCharset();
}
/**
* Returns the set of source {@code FileRef}s relative to this
* {@code SourcePathFileSystem}.
*/
public Set getSourceFileRefs() {
return Collections.unmodifiableSet(spFsToWrappedFsSourceFileRef.keySet());
}
private FileRef toWrappedFsFileRef(FileRef fnam, boolean forWriting) {
FileRef result = spFsToWrappedFsSourceFileRef.get(fnam);
if (result == null) {
result = outDir.join(fnam.getName());
} else if (forWriting) {
return null;
}
return result;
}
private final Function FROM_WRAPPED_FS_FILEREF
= new Function() {
public FileRef apply(FileRef fnam) {
FileRef result = wrappedFsToSpFsSourceFileRef.get(fnam);
if (result == null) {
// can't do outDir.isAncenstorOf(fnam) because FileSystems of fnam and outDir can differ
if (outDir.getName().equals("/") || fnam.getName().startsWith(outDir.getName() + "/")) {
return chop(outDir, fnam);
} else {
throw new IllegalArgumentException(fnam + " not in " + outDir + " or in source list");
}
}
return result;
}
};
}