001: /*
002: #IFNDEF ALT_LICENSE
003: ThinWire(R) RIA Ajax Framework
004: Copyright (C) 2003-2007 Custom Credit Systems
005:
006: This library is free software; you can redistribute it and/or modify it under
007: the terms of the GNU Lesser General Public License as published by the Free
008: Software Foundation; either version 2.1 of the License, or (at your option) any
009: later version.
010:
011: This library is distributed in the hope that it will be useful, but WITHOUT ANY
012: WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
013: PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
014:
015: You should have received a copy of the GNU Lesser General Public License along
016: with this library; if not, write to the Free Software Foundation, Inc., 59
017: Temple Place, Suite 330, Boston, MA 02111-1307 USA
018:
019: Users who would rather have a commercial license, warranty or support should
020: contact the following company who invented, built and supports the technology:
021:
022: Custom Credit Systems, Richardson, TX 75081, USA.
023: email: info@thinwire.com ph: +1 (888) 644-6405
024: http://www.thinwire.com
025: #ENDIF
026: [ v1.2_RC2 ]
027: */
028: package thinwire.render.web;
029:
030: import java.io.File;
031: import java.io.FileNotFoundException;
032: import java.io.IOException;
033: import java.util.HashMap;
034: import java.util.Map;
035: import java.util.logging.Level;
036: import java.util.logging.Logger;
037:
038: /**
039: * @author Joshua J. Gertzen
040: */
041: final class RemoteFileMap {
042: private static final Logger log = Logger
043: .getLogger(RemoteFileMap.class.getName());
044: private static final Level LEVEL = Level.FINER;
045: static final RemoteFileMap INSTANCE = new RemoteFileMap(128);
046:
047: private static final class RemoteFileInfo {
048: private int refCount;
049: private String remoteName;
050: private String localName;
051: private byte[] data;
052: }
053:
054: private Map<String, RemoteFileInfo> remoteToFileInfo;
055: private Map<String, RemoteFileInfo> localToFileInfo;
056:
057: private RemoteFileMap(int initialMapSize) {
058: remoteToFileInfo = new HashMap<String, RemoteFileInfo>(
059: initialMapSize);
060: localToFileInfo = new HashMap<String, RemoteFileInfo>(
061: initialMapSize);
062: }
063:
064: final String getLocalName(String remoteName) {
065: RemoteFileInfo fileInfo = remoteToFileInfo.get(remoteName);
066: return fileInfo == null ? null : fileInfo.localName;
067: }
068:
069: final byte[] load(String remoteName) {
070: RemoteFileInfo fileInfo = remoteToFileInfo.get(remoteName);
071:
072: if (fileInfo != null) {
073: byte[] data;
074:
075: if (fileInfo.data == null) {
076: data = WebApplication
077: .getResourceBytes(fileInfo.localName);
078: } else {
079: data = fileInfo.data;
080: }
081:
082: if (log.isLoggable(LEVEL))
083: log.log(LEVEL,
084: "Loaded file data for local file: localName='"
085: + fileInfo.localName
086: + "', remoteName='"
087: + fileInfo.remoteName + "', refCount='"
088: + fileInfo.refCount
089: + "', data.length='" + data.length
090: + "'");
091:
092: return data;
093: } else {
094: throw new RuntimeException(
095: new FileNotFoundException(
096: "The specified remote file '"
097: + remoteName
098: + "' does not have a mapping to a local file"));
099: }
100: }
101:
102: String add(String localName) {
103: return add(localName, null, null);
104: }
105:
106: String add(String localName, String remoteName) {
107: return add(localName, remoteName, null);
108: }
109:
110: String add(String localName, String remoteName, byte[] data) {
111: synchronized (localToFileInfo) {
112: RemoteFileInfo fileInfo = localToFileInfo.get(localName);
113:
114: if (fileInfo == null) {
115: fileInfo = new RemoteFileInfo();
116: fileInfo.localName = localName;
117: fileInfo.refCount = 1;
118: fileInfo.data = data;
119:
120: if (remoteName == null) {
121: int lastIndex = fileInfo.localName
122: .lastIndexOf(File.separatorChar);
123: if (lastIndex == -1)
124: lastIndex = fileInfo.localName
125: .lastIndexOf(File.separatorChar == '/' ? '\\'
126: : '/');
127: fileInfo.remoteName = fileInfo.localName
128: .substring(lastIndex + 1);
129:
130: if (remoteToFileInfo
131: .containsKey(fileInfo.remoteName)) {
132: lastIndex = fileInfo.remoteName
133: .lastIndexOf('.');
134: String file, ext;
135:
136: if (lastIndex == -1) {
137: file = fileInfo.remoteName;
138: ext = "";
139: } else {
140: file = fileInfo.remoteName.substring(0,
141: lastIndex);
142: ext = fileInfo.remoteName
143: .substring(lastIndex);
144: }
145:
146: StringBuilder sb = new StringBuilder();
147: int i = 0;
148:
149: do {
150: i++;
151: sb.append(file).append('-').append(i)
152: .append(ext);
153: fileInfo.remoteName = sb.toString();
154: sb.setLength(0);
155: } while (remoteToFileInfo
156: .containsKey(fileInfo.remoteName));
157: }
158: } else {
159: fileInfo.remoteName = remoteName;
160: }
161:
162: localToFileInfo.put(localName, fileInfo);
163: remoteToFileInfo.put(fileInfo.remoteName, fileInfo);
164: } else {
165: fileInfo.refCount++;
166: }
167:
168: if (log.isLoggable(LEVEL))
169: log.log(LEVEL,
170: "Added file mapping for local file: localName='"
171: + localName + "', remoteName='"
172: + fileInfo.remoteName + "', refCount='"
173: + fileInfo.refCount + "'");
174:
175: return fileInfo.remoteName;
176: }
177: }
178:
179: void remove(String localName) throws IOException {
180: synchronized (localToFileInfo) {
181: RemoteFileInfo fileInfo = localToFileInfo.get(localName);
182:
183: if (fileInfo != null) {
184: fileInfo.refCount--;
185:
186: if (fileInfo.refCount <= 0) {
187: localToFileInfo.remove(localName);
188: remoteToFileInfo.remove(fileInfo.remoteName);
189: }
190: }
191:
192: if (log.isLoggable(LEVEL))
193: log.log(LEVEL,
194: "Removed file mapping for local file: localName='"
195: + localName
196: + "'"
197: + (fileInfo == null ? ""
198: : ", remoteName='"
199: + fileInfo.remoteName
200: + "', refCount='"
201: + fileInfo.refCount
202: + "'"));
203: }
204: }
205: }
|