Many changes and fixes in Prototype skin management:
- Use an ordered TreeSet for prototype's repositories so we know the resources we get are already in the right order. - Use SkinMap again for intetracking mapping the prototype's skins internally after cleaning the code up a bit. - Add new ScriptableSkinMap object that wraps a skinmap, exposes it as native JavaScript object by extending WrappedMap, and does the Resource to String conversion in get(). - Move code that loads additional skins from skinpath from SkinManager.getSkinFiles() to SkinMap.loadSkinFiles() - Inline addSkinResource() and addCodeResource() methods into checkForUpdates(). - Make lastUpdate kind of fields volatile.
This commit is contained in:
parent
1c9bdff6af
commit
43b1b5edd8
3 changed files with 113 additions and 143 deletions
|
@ -23,7 +23,6 @@ import helma.util.WrappedMap;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -443,7 +442,7 @@ public class ApplicationBean implements Serializable {
|
||||||
for (Iterator it = app.getPrototypes().iterator(); it.hasNext();) {
|
for (Iterator it = app.getPrototypes().iterator(); it.hasNext();) {
|
||||||
Prototype p = (Prototype) it.next();
|
Prototype p = (Prototype) it.next();
|
||||||
|
|
||||||
Object skinmap = p.getSkinMap();
|
Object skinmap = p.getScriptableSkinMap();
|
||||||
skinz.put(p.getName(), skinmap);
|
skinz.put(p.getName(), skinmap);
|
||||||
skinz.put(p.getLowerCaseName(), skinmap);
|
skinz.put(p.getLowerCaseName(), skinmap);
|
||||||
}
|
}
|
||||||
|
@ -464,7 +463,7 @@ public class ApplicationBean implements Serializable {
|
||||||
for (Iterator it = app.getPrototypes().iterator(); it.hasNext();) {
|
for (Iterator it = app.getPrototypes().iterator(); it.hasNext();) {
|
||||||
Prototype p = (Prototype) it.next();
|
Prototype p = (Prototype) it.next();
|
||||||
|
|
||||||
Object skinmap = p.getSkinMap(skinpath);
|
Object skinmap = p.getScriptableSkinMap(skinpath);
|
||||||
skinz.put(p.getName(), skinmap);
|
skinz.put(p.getName(), skinmap);
|
||||||
skinz.put(p.getLowerCaseName(), skinmap);
|
skinz.put(p.getLowerCaseName(), skinmap);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,12 @@
|
||||||
package helma.framework.core;
|
package helma.framework.core;
|
||||||
|
|
||||||
import helma.objectmodel.db.DbMapping;
|
import helma.objectmodel.db.DbMapping;
|
||||||
import helma.util.SystemMap;
|
|
||||||
import helma.util.ResourceProperties;
|
import helma.util.ResourceProperties;
|
||||||
|
import helma.util.WrappedMap;
|
||||||
import helma.framework.repository.Resource;
|
import helma.framework.repository.Resource;
|
||||||
import helma.framework.repository.Repository;
|
import helma.framework.repository.Repository;
|
||||||
import helma.framework.repository.ResourceTracker;
|
import helma.framework.repository.ResourceTracker;
|
||||||
|
import helma.framework.repository.FileResource;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -47,18 +48,18 @@ public final class Prototype {
|
||||||
long lastChecksum = -1;
|
long lastChecksum = -1;
|
||||||
|
|
||||||
// the time at which any of the prototype's files were found updated the last time
|
// the time at which any of the prototype's files were found updated the last time
|
||||||
long lastCodeUpdate = 0;
|
volatile long lastCodeUpdate = 0;
|
||||||
|
|
||||||
TreeSet code;
|
TreeSet code;
|
||||||
TreeSet skins;
|
TreeSet skins;
|
||||||
|
|
||||||
HashMap trackers;
|
HashMap trackers;
|
||||||
|
|
||||||
HashSet repositories;
|
TreeSet repositories;
|
||||||
|
|
||||||
// a map of this prototype's skins as raw strings
|
// a map of this prototype's skins as raw strings
|
||||||
// used for exposing skins to application (script) code (via app.skinfiles).
|
// used for exposing skins to application (script) code (via app.skinfiles).
|
||||||
HashMap skinMap;
|
SkinMap skinMap;
|
||||||
|
|
||||||
DbMapping dbmap;
|
DbMapping dbmap;
|
||||||
|
|
||||||
|
@ -81,7 +82,7 @@ public final class Prototype {
|
||||||
// app.logEvent ("Constructing Prototype "+app.getName()+"/"+name);
|
// app.logEvent ("Constructing Prototype "+app.getName()+"/"+name);
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
repositories = new HashSet();
|
repositories = new TreeSet(app.getResourceComparator());
|
||||||
if (repository != null) {
|
if (repository != null) {
|
||||||
repositories.add(repository);
|
repositories.add(repository);
|
||||||
}
|
}
|
||||||
|
@ -102,7 +103,7 @@ public final class Prototype {
|
||||||
|
|
||||||
trackers = new HashMap();
|
trackers = new HashMap();
|
||||||
|
|
||||||
skinMap = new HashMap();
|
skinMap = new SkinMap();
|
||||||
|
|
||||||
isJavaPrototype = app.isJavaPrototype(name);
|
isJavaPrototype = app.isJavaPrototype(name);
|
||||||
}
|
}
|
||||||
|
@ -170,10 +171,11 @@ public final class Prototype {
|
||||||
name.endsWith(TypeManager.skinExtension)) {
|
name.endsWith(TypeManager.skinExtension)) {
|
||||||
updatedResources = true;
|
updatedResources = true;
|
||||||
if (name.endsWith(TypeManager.skinExtension)) {
|
if (name.endsWith(TypeManager.skinExtension)) {
|
||||||
addSkinResource(resources[i]);
|
skins.add(resources[i]);
|
||||||
} else {
|
} else {
|
||||||
addCodeResource(resources[i]);
|
code.add(resources[i]);
|
||||||
}
|
}
|
||||||
|
trackers.put(resources[i].getName(), new ResourceTracker(resources[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,28 +308,13 @@ public final class Prototype {
|
||||||
return dbmap;
|
return dbmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a Skinfile for this prototype. This only works for skins
|
|
||||||
* residing in the prototype directory, not for skin files in
|
|
||||||
* other locations or database stored skins.
|
|
||||||
*/
|
|
||||||
public Resource getSkinResource(String sname) {
|
|
||||||
return (Resource) skinMap.get(sname);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a skin for this prototype. This only works for skins
|
* Get a skin for this prototype. This only works for skins
|
||||||
* residing in the prototype directory, not for skins files in
|
* residing in the prototype directory, not for skins files in
|
||||||
* other locations or database stored skins.
|
* other locations or database stored skins.
|
||||||
*/
|
*/
|
||||||
public Skin getSkin(String sname) throws IOException {
|
public Skin getSkin(String sname) throws IOException {
|
||||||
Resource res = getSkinResource(sname);
|
return skinMap.getSkin(name);
|
||||||
|
|
||||||
if (res != null) {
|
|
||||||
return Skin.getSkin(res, app);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -373,28 +360,6 @@ public final class Prototype {
|
||||||
return code.iterator();
|
return code.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a code resource to this prototype
|
|
||||||
*
|
|
||||||
* @param res a code resource
|
|
||||||
*/
|
|
||||||
public synchronized void addCodeResource(Resource res) {
|
|
||||||
code.add(res);
|
|
||||||
trackers.put(res.getName(), new ResourceTracker(res));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a skin resource to this prototype
|
|
||||||
*
|
|
||||||
* @param res a skin resource
|
|
||||||
*/
|
|
||||||
public synchronized void addSkinResource(Resource res) {
|
|
||||||
skins.add(res);
|
|
||||||
skinMap.put(res.getBaseName(), res);
|
|
||||||
trackers.put(res.getName(), new ResourceTracker(res));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a string representing this prototype.
|
* Return a string representing this prototype.
|
||||||
*/
|
*/
|
||||||
|
@ -403,68 +368,39 @@ public final class Prototype {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get a map containing this prototype's skins as strings
|
||||||
*
|
*
|
||||||
*
|
* @return
|
||||||
* @return ...
|
|
||||||
*/
|
*/
|
||||||
public SkinMap getSkinMap() {
|
public Map getScriptableSkinMap() {
|
||||||
return new SkinMap();
|
return new ScriptableSkinMap(new SkinMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
// not yet implemented
|
/**
|
||||||
public SkinMap getSkinMap(Object[] skinpath) {
|
* Get a map containing this prototype's skins as strings, overloaded by the
|
||||||
return new SkinMap(skinpath);
|
* skins found in the given skinpath.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Map getScriptableSkinMap(Object[] skinpath) {
|
||||||
|
return new ScriptableSkinMap(new SkinMap(skinpath));
|
||||||
}
|
}
|
||||||
|
|
||||||
// a map that dynamically expands to all skins in this prototype
|
/**
|
||||||
final class SkinMap extends SystemMap {
|
* A map of this prototype's skins that acts as a native JavaScript object in
|
||||||
long lastSkinmapLoad = -1;
|
* rhino and returns the skins as strings. This is used to expose the skins
|
||||||
Object[] skinpath;
|
* to JavaScript in app.skinfiles[prototypeName][skinName].
|
||||||
|
*/
|
||||||
|
class ScriptableSkinMap extends WrappedMap {
|
||||||
|
|
||||||
SkinMap() {
|
public ScriptableSkinMap(Map wrapped) {
|
||||||
super();
|
super(wrapped);
|
||||||
skinpath = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
SkinMap(Object[] path) {
|
|
||||||
super();
|
|
||||||
skinpath = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean containsKey(Object key) {
|
|
||||||
checkForUpdates();
|
|
||||||
|
|
||||||
return super.containsKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean containsValue(Object value) {
|
|
||||||
checkForUpdates();
|
|
||||||
|
|
||||||
return super.containsValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set entrySet() {
|
|
||||||
checkForUpdates();
|
|
||||||
|
|
||||||
return super.entrySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
checkForUpdates();
|
|
||||||
|
|
||||||
return super.equals(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object get(Object key) {
|
public Object get(Object key) {
|
||||||
if (key == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkForUpdates();
|
|
||||||
|
|
||||||
Resource res = (Resource) super.get(key);
|
Resource res = (Resource) super.get(key);
|
||||||
|
|
||||||
if (res == null) {
|
if (res == null || !res.exists()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,22 +410,70 @@ public final class Prototype {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Map that dynamically expands to all skins in this prototype.
|
||||||
|
*/
|
||||||
|
class SkinMap extends HashMap {
|
||||||
|
volatile long lastSkinmapLoad = -1;
|
||||||
|
Object[] skinpath;
|
||||||
|
|
||||||
|
SkinMap() {
|
||||||
|
skinpath = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkinMap(Object[] path) {
|
||||||
|
skinpath = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsKey(Object key) {
|
||||||
|
checkForUpdates();
|
||||||
|
return super.containsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsValue(Object value) {
|
||||||
|
checkForUpdates();
|
||||||
|
return super.containsValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set entrySet() {
|
||||||
|
checkForUpdates();
|
||||||
|
return super.entrySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
checkForUpdates();
|
||||||
|
return super.equals(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Skin getSkin(Object key) throws IOException {
|
||||||
|
Resource res = (Resource) super.get(key);
|
||||||
|
|
||||||
|
if (res != null) {
|
||||||
|
return Skin.getSkin(res, app);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object get(Object key) {
|
||||||
|
checkForUpdates();
|
||||||
|
return super.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
checkForUpdates();
|
checkForUpdates();
|
||||||
|
|
||||||
return super.hashCode();
|
return super.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
checkForUpdates();
|
checkForUpdates();
|
||||||
|
|
||||||
return super.isEmpty();
|
return super.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set keySet() {
|
public Set keySet() {
|
||||||
checkForUpdates();
|
checkForUpdates();
|
||||||
|
|
||||||
return super.keySet();
|
return super.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,19 +489,16 @@ public final class Prototype {
|
||||||
|
|
||||||
public Object remove(Object key) {
|
public Object remove(Object key) {
|
||||||
checkForUpdates();
|
checkForUpdates();
|
||||||
|
|
||||||
return super.remove(key);
|
return super.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
checkForUpdates();
|
checkForUpdates();
|
||||||
|
|
||||||
return super.size();
|
return super.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection values() {
|
public Collection values() {
|
||||||
checkForUpdates();
|
checkForUpdates();
|
||||||
|
|
||||||
return super.values();
|
return super.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,11 +508,11 @@ public final class Prototype {
|
||||||
// if prototype resources haven't been checked yet, check them now
|
// if prototype resources haven't been checked yet, check them now
|
||||||
Prototype.this.checkForUpdates();
|
Prototype.this.checkForUpdates();
|
||||||
}
|
}
|
||||||
load();
|
loadSkins();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void load() {
|
private synchronized void loadSkins() {
|
||||||
if (lastCodeUpdate == lastSkinmapLoad) {
|
if (lastCodeUpdate == lastSkinmapLoad) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -541,7 +522,6 @@ public final class Prototype {
|
||||||
// load Skins
|
// load Skins
|
||||||
for (Iterator i = skins.iterator(); i.hasNext();) {
|
for (Iterator i = skins.iterator(); i.hasNext();) {
|
||||||
Resource res = (Resource) i.next();
|
Resource res = (Resource) i.next();
|
||||||
|
|
||||||
super.put(res.getBaseName(), res);
|
super.put(res.getBaseName(), res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,12 +529,7 @@ public final class Prototype {
|
||||||
if (skinpath != null) {
|
if (skinpath != null) {
|
||||||
for (int i = skinpath.length - 1; i >= 0; i--) {
|
for (int i = skinpath.length - 1; i >= 0; i--) {
|
||||||
if ((skinpath[i] != null) && skinpath[i] instanceof String) {
|
if ((skinpath[i] != null) && skinpath[i] instanceof String) {
|
||||||
Map m = app.skinmgr.getSkinFiles((String) skinpath[i],
|
loadSkinFiles((String) skinpath[i]);
|
||||||
Prototype.this);
|
|
||||||
|
|
||||||
if (m != null) {
|
|
||||||
super.putAll(m);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -562,6 +537,31 @@ public final class Prototype {
|
||||||
lastSkinmapLoad = lastCodeUpdate;
|
lastSkinmapLoad = lastCodeUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loadSkinFiles(String skinDir) {
|
||||||
|
File dir = new File(skinDir.toString(), Prototype.this.getName());
|
||||||
|
// if directory does not exist use lower case property name
|
||||||
|
if (!dir.isDirectory()) {
|
||||||
|
dir = new File(skinDir.toString(), Prototype.this.getLowerCaseName());
|
||||||
|
if (!dir.isDirectory()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] skinNames = dir.list(app.skinmgr);
|
||||||
|
|
||||||
|
if ((skinNames == null) || (skinNames.length == 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < skinNames.length; i++) {
|
||||||
|
String name = skinNames[i].substring(0, skinNames[i].length() - 5);
|
||||||
|
File file = new File(dir, skinNames[i]);
|
||||||
|
|
||||||
|
super.put(name, (new FileResource(file)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[SkinMap " + name + "]";
|
return "[SkinMap " + name + "]";
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import helma.objectmodel.INode;
|
||||||
import helma.framework.repository.FileResource;
|
import helma.framework.repository.FileResource;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages skins for a Helma application
|
* Manages skins for a Helma application
|
||||||
|
@ -121,34 +120,6 @@ public final class SkinManager implements FilenameFilter {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map getSkinFiles(String skinDir, Prototype proto) {
|
|
||||||
File dir = new File(skinDir.toString(), proto.getName());
|
|
||||||
// if directory does not exist use lower case property name
|
|
||||||
if (!dir.isDirectory()) {
|
|
||||||
dir = new File(skinDir.toString(), proto.getLowerCaseName());
|
|
||||||
if (!dir.isDirectory()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] skinNames = dir.list(this);
|
|
||||||
|
|
||||||
if ((skinNames == null) || (skinNames.length == 0)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
HashMap map = new HashMap();
|
|
||||||
|
|
||||||
for (int i = 0; i < skinNames.length; i++) {
|
|
||||||
String name = skinNames[i].substring(0, skinNames[i].length() - 5);
|
|
||||||
File file = new File(dir, skinNames[i]);
|
|
||||||
|
|
||||||
map.put(name, (new FileResource(file)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements java.io.FilenameFilter.accept()
|
* Implements java.io.FilenameFilter.accept()
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Reference in a new issue