r9632 - in helma-ng/trunk/src/org/helma: javascript repository tools
[email protected] Mon, 20 Apr 2009 18:31:16 +0200 (CEST)
| Newsgroups | gmane.comp.java.helma.cvs |
|---|---|
| Message-ID | <20090420163116.1FB643D0D6@mia> |
Author: hannes
Date: 2009-04-20 18:31:15 +0200 (Mon, 20 Apr 2009)
New Revision: 9632
Modified:
helma-ng/trunk/src/org/helma/javascript/ReloadableScript.java
helma-ng/trunk/src/org/helma/javascript/RhinoEngine.java
helma-ng/trunk/src/org/helma/repository/AbstractRepository.java
helma-ng/trunk/src/org/helma/repository/AbstractResource.java
helma-ng/trunk/src/org/helma/repository/FileRepository.java
helma-ng/trunk/src/org/helma/repository/FileResource.java
helma-ng/trunk/src/org/helma/repository/Repository.java
helma-ng/trunk/src/org/helma/repository/Resource.java
helma-ng/trunk/src/org/helma/repository/Trackable.java
helma-ng/trunk/src/org/helma/repository/WebappRepository.java
helma-ng/trunk/src/org/helma/repository/ZipRepository.java
helma-ng/trunk/src/org/helma/repository/ZipResource.java
helma-ng/trunk/src/org/helma/tools/HelmaConfiguration.java
Log:
Fix several issues in resource framework (trac ticket #26)
* Add new methods in Resource/Repository/Trackable interfaces to
mark root repositories and get relative repository paths
* Disallow escaping repository roots via ".." paths
* Provide modules a method to retrieve canonical module names
* Allow "." to be resolved across root repositories
* Add new resolveRootRepository() method in HelmaConfiguration to
make it easier to add repositories programmatically
Details at http://dev.helma.org/trac/helma/changeset/9632
Modified: helma-ng/trunk/src/org/helma/javascript/ReloadableScript.java
===================================================================
--- helma-ng/trunk/src/org/helma/javascript/ReloadableScript.java 2009-04-20 16:31:11 UTC (rev 9631)
+++ helma-ng/trunk/src/org/helma/javascript/ReloadableScript.java 2009-04-20 16:31:15 UTC (rev 9632)
@@ -34,6 +34,7 @@
final Trackable source;
final RhinoEngine engine;
+ final String moduleName;
// the checksum of the underlying resource or repository when
// the script was last compiled
long checksum = -1;
@@ -60,6 +61,7 @@
public ReloadableScript(Trackable source, RhinoEngine engine) {
this.source = source;
this.engine = engine;
+ moduleName = source.getModuleName();
}
/**
@@ -101,7 +103,7 @@
Resource resource = (Resource) source;
try {
exception = null;
- script = cx.compileReader(resource.getReader(), resource.getPath(), 1, null);
+ script = cx.compileReader(resource.getReader(), resource.getRelativePath(), 1, null);
} catch (Exception x) {
exception = x;
} finally {
@@ -129,7 +131,7 @@
exception = null;
for (Resource res: resources) {
if (res.getName().endsWith(".js")) {
- scripts.add(cx.compileReader(res.getReader(), res.getPath(), 1, null));
+ scripts.add(cx.compileReader(res.getReader(), res.getRelativePath(), 1, null));
}
}
} catch (Exception x) {
@@ -180,13 +182,12 @@
* Get a module scope loaded with this script
*
* @param prototype the prototype for the module, usually the shared top level scope
- * @param moduleName the module name
* @param cx the rhino context
* @return a new module scope
* @throws JavaScriptException if an error occurred evaluating the script file
* @throws IOException if an error occurred reading the script file
*/
- protected synchronized Scriptable load(Scriptable prototype, String moduleName, Context cx)
+ protected synchronized Scriptable load(Scriptable prototype, Context cx)
throws JavaScriptException, IOException {
// check if we already came across the module in the current context/request
Map<Trackable,Scriptable> modules = (Map<Trackable,Scriptable>) cx.getThreadLocal("modules");
Modified: helma-ng/trunk/src/org/helma/javascript/RhinoEngine.java
===================================================================
--- helma-ng/trunk/src/org/helma/javascript/RhinoEngine.java 2009-04-20 16:31:11 UTC (rev 9631)
+++ helma-ng/trunk/src/org/helma/javascript/RhinoEngine.java 2009-04-20 16:31:15 UTC (rev 9632)
@@ -148,7 +148,7 @@
interpretedScripts : compiledScripts;
commandLineArgs = Arrays.asList(scriptArgs);
Resource resource = findResource(scriptName, null);
- if (!resource.exists()) {
+ if (resource == null || !resource.exists()) {
resource = new FileResource(new File(scriptName));
}
if (!resource.exists()) {
@@ -389,7 +389,7 @@
ReloadableScript parent = getCurrentScript(cx);
try {
setCurrentScript(cx, script);
- module = script.load(topLevelScope, moduleName, cx);
+ module = script.load(topLevelScope, cx);
} finally {
if (parent != null) {
parent.addDependency(script);
@@ -491,10 +491,10 @@
/**
* Search for a resource in a local path, or the main repository path.
* @param path the resource name
- * @param localPath a repository to look first
+ * @param localRoot a repository to look first
* @return the resource
*/
- public Resource findResource(String path, Repository localPath) {
+ public Resource findResource(String path, Repository localRoot) {
// FIXME: we allow absolute module paths, and we do not check
// if relative paths escape their root repository. These are
// of course gaping security holes for environments running
@@ -502,8 +502,8 @@
File file = new File(path);
if (file.isAbsolute()) {
return new FileResource(file);
- } else if (localPath != null && path.startsWith(".")) {
- return localPath.getResource(path);
+ } else if (localRoot != null && path.startsWith(".")) {
+ return findResource(localRoot.getRelativePath() + path, null);
} else {
return config.getResource(path);
}
Modified: helma-ng/trunk/src/org/helma/repository/AbstractRepository.java
===================================================================
--- helma-ng/trunk/src/org/helma/repository/AbstractRepository.java 2009-04-20 16:31:11 UTC (rev 9631)
+++ helma-ng/trunk/src/org/helma/repository/AbstractRepository.java 2009-04-20 16:31:15 UTC (rev 9632)
@@ -31,7 +31,7 @@
/**
* Parent repository this repository is contained in.
*/
- Repository parent;
+ AbstractRepository parent;
/**
* Holds direct child repositories
@@ -91,6 +91,44 @@
}
/**
+ * Mark this repository as root repository.
+ */
+ public void setRoot() {
+ parent = null;
+ }
+
+ /**
+ * Get the path of this repository relative to its root repository.
+ *
+ * @return the repository path
+ */
+ public String getRelativePath() {
+ if (parent == null) {
+ return "";
+ } else {
+ StringBuffer b = new StringBuffer();
+ getRelativePath(b);
+ return b.toString();
+ }
+ }
+
+ protected void getRelativePath(StringBuffer buffer) {
+ if (parent != null) {
+ parent.getRelativePath(buffer);
+ buffer.append(name).append('/');
+ }
+ }
+
+ /**
+ * Utility method to get the name for the module defined by this resource.
+ *
+ * @return the module name according to the securable module spec
+ */
+ public String getModuleName() {
+ return getRelativePath();
+ }
+
+ /**
* Get a resource contained in this repository identified by the given local name.
* If the name can't be resolved to a resource, a resource object is returned
* for which {@link Resource exists()} returns <code>false<code>.
@@ -107,10 +145,10 @@
}
Repository repository = this;
int i = 0;
- while (i < subs.length - 1) {
+ while (repository != null && i < subs.length - 1) {
repository = repository.getChildRepository(subs[i++]);
}
- return repository.getResource(subs[i]);
+ return repository == null ? null : repository.getResource(subs[i]);
}
/**
@@ -165,6 +203,8 @@
return allResources;
}
+
+
/**
* Returns the repositories full name as string representation.
* @see {getName()}
Modified: helma-ng/trunk/src/org/helma/repository/AbstractResource.java
===================================================================
--- helma-ng/trunk/src/org/helma/repository/AbstractResource.java 2009-04-20 16:31:11 UTC (rev 9631)
+++ helma-ng/trunk/src/org/helma/repository/AbstractResource.java 2009-04-20 16:31:15 UTC (rev 9632)
@@ -7,7 +7,7 @@
public abstract class AbstractResource implements Resource {
- protected Repository repository;
+ protected AbstractRepository repository;
protected String path;
protected String name;
protected String baseName;
@@ -56,6 +56,38 @@
return getContent(null);
}
+ /**
+ * Get the path of this resource relative to its root repository.
+ *
+ * @return the relative resource path
+ */
+ public String getRelativePath() {
+ if (repository == null) {
+ return name;
+ } else {
+ StringBuffer b = new StringBuffer();
+ repository.getRelativePath(b);
+ b.append(name);
+ return b.toString();
+ }
+ }
+
+ /**
+ * Utility method to get the name for the module defined by this resource.
+ *
+ * @return the module name according to the securable module spec
+ */
+ public String getModuleName() {
+ if (repository == null) {
+ return baseName;
+ } else {
+ StringBuffer b = new StringBuffer();
+ repository.getRelativePath(b);
+ b.append(baseName);
+ return b.toString();
+ }
+ }
+
public long getChecksum() {
return lastModified();
}
Modified: helma-ng/trunk/src/org/helma/repository/FileRepository.java
===================================================================
--- helma-ng/trunk/src/org/helma/repository/FileRepository.java 2009-04-20 16:31:11 UTC (rev 9631)
+++ helma-ng/trunk/src/org/helma/repository/FileRepository.java 2009-04-20 16:31:15 UTC (rev 9632)
@@ -96,6 +96,11 @@
* @return the child repository
*/
public Repository getChildRepository(String name) {
+ if (".".equals(name)) {
+ return this;
+ } else if ("..".equals(name)) {
+ return parent;
+ }
return new FileRepository(new File(directory, name), this);
}
Modified: helma-ng/trunk/src/org/helma/repository/FileResource.java
===================================================================
--- helma-ng/trunk/src/org/helma/repository/FileResource.java 2009-04-20 16:31:11 UTC (rev 9631)
+++ helma-ng/trunk/src/org/helma/repository/FileResource.java 2009-04-20 16:31:15 UTC (rev 9632)
@@ -20,20 +20,16 @@
import java.net.MalformedURLException;
import java.net.URL;
-public class FileResource implements Resource {
+public class FileResource extends AbstractResource {
File file;
- Repository repository;
- String path;
- String name;
- String baseName;
boolean stripShebang = false;
public FileResource(File file) {
this(file, null);
}
- protected FileResource(File file, Repository repository) {
+ protected FileResource(File file, FileRepository repository) {
// make sure our directory has an absolute path,
// see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4117557
try {
@@ -52,18 +48,6 @@
baseName = (lastDot == -1) ? name : name.substring(0, lastDot);
}
- public String getPath() {
- return path;
- }
-
- public String getName() {
- return name;
- }
-
- public String getBaseName() {
- return baseName;
- }
-
public InputStream getInputStream() throws IOException {
InputStream stream = new FileInputStream(file);
if (stripShebang) {
@@ -89,10 +73,6 @@
return stream;
}
- public Reader getReader() throws IOException {
- return new InputStreamReader(getInputStream());
- }
-
public URL getUrl() throws MalformedURLException {
return new URL("file:" + file.getAbsolutePath());
}
@@ -101,32 +81,6 @@
return file.lastModified();
}
- public long getChecksum() {
- return lastModified();
- }
-
- public String getContent(String encoding) throws IOException {
- InputStream in = getInputStream();
- int size = (int) file.length();
- byte[] buf = new byte[size];
- int read = 0;
- while (read < size) {
- int r = in.read(buf, read, size - read);
- if (r == -1)
- break;
- read += r;
- }
- if (in != null)
- in.close();
- return encoding == null ?
- new String(buf) :
- new String(buf, encoding);
- }
-
- public String getContent() throws IOException {
- return getContent(null);
- }
-
public long getLength() {
return file.length();
}
Modified: helma-ng/trunk/src/org/helma/repository/Repository.java
===================================================================
--- helma-ng/trunk/src/org/helma/repository/Repository.java 2009-04-20 16:31:11 UTC (rev 9631)
+++ helma-ng/trunk/src/org/helma/repository/Repository.java 2009-04-20 16:31:15 UTC (rev 9632)
@@ -68,4 +68,15 @@
*/
public Repository getChildRepository(String name);
+ /**
+ * Mark this repository as root repository.
+ */
+ public void setRoot();
+
+ /**
+ * Get the path of this repository relative to its root repository.
+ * @return the repository path
+ */
+ public String getRelativePath();
+
}
\ No newline at end of file
Modified: helma-ng/trunk/src/org/helma/repository/Resource.java
===================================================================
--- helma-ng/trunk/src/org/helma/repository/Resource.java 2009-04-20 16:31:11 UTC (rev 9631)
+++ helma-ng/trunk/src/org/helma/repository/Resource.java 2009-04-20 16:31:15 UTC (rev 9632)
@@ -69,4 +69,10 @@
*/
public String getBaseName();
+ /**
+ * Get the path of this resource relative to its root repository.
+ * @return the relative resource path
+ */
+ public String getRelativePath();
+
}
Modified: helma-ng/trunk/src/org/helma/repository/Trackable.java
===================================================================
--- helma-ng/trunk/src/org/helma/repository/Trackable.java 2009-04-20 16:31:11 UTC (rev 9631)
+++ helma-ng/trunk/src/org/helma/repository/Trackable.java 2009-04-20 16:31:15 UTC (rev 9632)
@@ -54,4 +54,10 @@
*/
public Repository getParentRepository();
+ /**
+ * Utility method to get the name for the module defined by this resource.
+ * @return the module name according to the securable module spec
+ */
+ public String getModuleName();
+
}
Modified: helma-ng/trunk/src/org/helma/repository/WebappRepository.java
===================================================================
--- helma-ng/trunk/src/org/helma/repository/WebappRepository.java 2009-04-20 16:31:11 UTC (rev 9631)
+++ helma-ng/trunk/src/org/helma/repository/WebappRepository.java 2009-04-20 16:31:15 UTC (rev 9632)
@@ -56,6 +56,11 @@
}
public Repository getChildRepository(String name) {
+ if (".".equals(name)) {
+ return this;
+ } else if ("..".equals(name)) {
+ return parent;
+ }
return new WebappRepository(context, this, name);
}
Modified: helma-ng/trunk/src/org/helma/repository/ZipRepository.java
===================================================================
--- helma-ng/trunk/src/org/helma/repository/ZipRepository.java 2009-04-20 16:31:11 UTC (rev 9631)
+++ helma-ng/trunk/src/org/helma/repository/ZipRepository.java 2009-04-20 16:31:15 UTC (rev 9632)
@@ -59,7 +59,7 @@
* repository
* @param file a zip file
*/
- protected ZipRepository(File file, Repository parent) {
+ protected ZipRepository(File file, AbstractRepository parent) {
this(file, parent, null);
}
@@ -70,7 +70,7 @@
* @param zipentry zip entryName
* @param parent repository
*/
- private ZipRepository(File file, Repository parent, ZipEntry zipentry) {
+ private ZipRepository(File file, AbstractRepository parent, ZipEntry zipentry) {
// make sure our file has an absolute path,
// see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4117557
if (file.isAbsolute()) {
@@ -222,6 +222,11 @@
* @return the child repository
*/
public Repository getChildRepository(String name) {
+ if (".".equals(name)) {
+ return this;
+ } else if ("..".equals(name)) {
+ return parent;
+ }
return new ZipRepository(file, this, new ZipEntry(entryPath + "/" + name));
}
Modified: helma-ng/trunk/src/org/helma/repository/ZipResource.java
===================================================================
--- helma-ng/trunk/src/org/helma/repository/ZipResource.java 2009-04-20 16:31:11 UTC (rev 9631)
+++ helma-ng/trunk/src/org/helma/repository/ZipResource.java 2009-04-20 16:31:15 UTC (rev 9632)
@@ -21,13 +21,9 @@
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
-public final class ZipResource implements Resource {
+public final class ZipResource extends AbstractResource {
private String entryName;
- private ZipRepository repository;
- private String path;
- private String name;
- private String baseName;
protected ZipResource(String zipentryName, ZipRepository repository) {
this.entryName = zipentryName;
@@ -55,7 +51,7 @@
public InputStream getInputStream() throws IOException {
ZipFile zipfile = null;
try {
- zipfile = repository.getZipFile();
+ zipfile = getZipFile();
ZipEntry entry = zipfile.getEntry(entryName);
if (entry == null) {
throw new IOException("Zip resource " + this + " does not exist");
@@ -81,14 +77,10 @@
}
}
- public Reader getReader() throws IOException {
- return new InputStreamReader(getInputStream());
- }
-
public boolean exists() {
ZipFile zipfile = null;
try {
- zipfile = repository.getZipFile();
+ zipfile = getZipFile();
return (zipfile.getEntry(entryName) != null);
} catch (Exception ex) {
return false;
@@ -104,7 +96,7 @@
public String getContent(String encoding) throws IOException {
ZipFile zipfile = null;
try {
- zipfile = repository.getZipFile();
+ zipfile = getZipFile();
ZipEntry entry = zipfile.getEntry(entryName);
if (entry == null) {
return "";
@@ -130,22 +122,6 @@
}
}
- public String getContent() throws IOException {
- return getContent(null);
- }
-
- public String getPath() {
- return path;
- }
-
- public String getName() {
- return name;
- }
-
- public String getBaseName() {
- return baseName;
- }
-
public URL getUrl() {
// TODO: we might want to return a Jar URL
// http://java.sun.com/j2se/1.5.0/docs/api/java/net/JarURLConnection.html
@@ -155,7 +131,7 @@
public long getLength() {
ZipFile zipfile = null;
try {
- zipfile = repository.getZipFile();
+ zipfile = getZipFile();
return zipfile.getEntry(entryName).getSize();
} catch (Exception ex) {
return 0;
@@ -186,4 +162,11 @@
public String toString() {
return getPath();
}
+
+ private ZipFile getZipFile() throws IOException {
+ if (!(repository instanceof ZipRepository)) {
+ throw new IOException("Parent is not a ZipRepository: " + repository);
+ }
+ return ((ZipRepository) repository).getZipFile();
+ }
}
Modified: helma-ng/trunk/src/org/helma/tools/HelmaConfiguration.java
===================================================================
--- helma-ng/trunk/src/org/helma/tools/HelmaConfiguration.java 2009-04-20 16:31:11 UTC (rev 9631)
+++ helma-ng/trunk/src/org/helma/tools/HelmaConfiguration.java 2009-04-20 16:31:15 UTC (rev 9632)
@@ -69,47 +69,66 @@
String[] paths = StringUtils.split(modulePath, File.pathSeparator);
for (int i = 0; i < paths.length; i++) {
String path = paths[i].trim();
- Repository repo = home.getChildRepository(path);
- if (repo.exists()) {
- repositories.add(repo);
- continue;
- }
- File file = new File(path);
- if (!file.isAbsolute()) {
- // if path is relative, try to resolve against current directory first,
- // then relative to helma installation directory.
- file = file.getAbsoluteFile();
- if (!file.exists()) {
- file = new File(home.getPath(), path);
- }
- }
- if (!file.exists()) {
- throw new FileNotFoundException("File '" + file + "' does not exist.");
- }
- if (path.toLowerCase().endsWith(".zip")) {
- repositories.add(new ZipRepository(file));
+ Repository repository = resolveRootRepository(path);
+ if (repository != null && repository.exists()) {
+ repositories.add(repository);
} else {
- if (i == 0 && file.isFile()) {
- Resource res = new FileResource(file);
- mainModule = res.getBaseName();
- repositories.add(res.getParentRepository());
- } else {
- repositories.add(new FileRepository(file));
- }
+ getLogger().error("Cannot resolve module path entry: " + path);
}
}
}
// append system modules path relative to helma home
if (systemModules != null) {
- Repository modules = home.getChildRepository(systemModules);
- repositories.add(modules);
+ Repository repository = resolveRootRepository(systemModules);
+ if (repository != null && repository.exists()) {
+ repositories.add(repository);
+ } else {
+ getLogger().error("Cannot resolve system module root: " + systemModules);
+ }
}
- Logger.getLogger("org.helma.tools").debug("Parsed repository list: " + repositories);
+ getLogger().debug("Parsed repository list: " + repositories);
}
/**
+ * Resolve a module repository path.
+ * @param path the path
+ * @return a repository
+ * @throws FileNotFoundException if the path couldn't be resolved
+ */
+ public Repository resolveRootRepository(String path) throws FileNotFoundException {
+ Repository repository = home.getChildRepository(path);
+ if (repository != null && repository.exists()) {
+ repository.setRoot();
+ return repository;
+ }
+ File file = new File(path);
+ if (!file.isAbsolute()) {
+ // if path is relative, try to resolve against current directory first,
+ // then relative to helma installation directory.
+ file = file.getAbsoluteFile();
+ if (!file.exists()) {
+ file = new File(home.getPath(), path);
+ }
+ }
+ if (!file.exists()) {
+ throw new FileNotFoundException("File '" + file + "' does not exist.");
+ }
+ if (path.toLowerCase().endsWith(".zip")) {
+ return new ZipRepository(file);
+ } else {
+ if (file.isFile()) {
+ Resource res = new FileResource(file);
+ mainModule = res.getBaseName();
+ return res.getParentRepository();
+ } else {
+ return new FileRepository(file);
+ }
+ }
+ }
+
+ /**
* If the scriptName argument is not null, prepend the script's parent repository
* to the module path. Otherwise, prepend the current working directory to the module path.
* @param scriptName the name of the script, or null.
@@ -216,7 +235,7 @@
public Resource getResource(String path) {
for (Repository repo: repositories) {
Resource res = repo.getResource(path);
- if (res.exists()) {
+ if (res != null && res.exists()) {
return res;
}
}
@@ -269,4 +288,8 @@
this.sealed = sealed;
}
+ private Logger getLogger() {
+ return Logger.getLogger("org.helma.tools");
+ }
+
}
\ No newline at end of file