001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.vfs;
031:
032: import com.caucho.loader.EnvironmentLocal;
033: import com.caucho.server.hmux.HmuxPath;
034: import com.caucho.util.CharBuffer;
035:
036: import java.io.IOException;
037: import java.io.InputStream;
038: import java.io.OutputStream;
039: import java.io.Reader;
040: import java.io.Writer;
041: import java.util.Map;
042:
043: /**
044: * Facade to create useful Path and Stream objects.
045: *
046: * <code><pre>
047: * Path path = Vfs.lookup("foo.html");
048: * </pre><code>
049: *
050: * <p>The default scheme is the file scheme. Other schemes are
051: * available using the full url.
052: *
053: * <code><pre>
054: * Path mail = Vfs.lookup("mailto:drofnats@foo.com.test?subject='hi'");
055: * Stream body = mail.openWrite();
056: * body.writeln("How's it going?");
057: * body.close();
058: * </pre><code>
059: */
060: public final class Vfs {
061: private static final EnvironmentLocal<Path> ENV_PWD = new EnvironmentLocal<Path>(
062: "caucho.vfs.pwd");
063:
064: private static final SchemeMap DEFAULT_SCHEME_MAP;
065:
066: private static final EnvironmentLocal<SchemeMap> _localSchemeMap = new EnvironmentLocal<SchemeMap>();
067:
068: static FilesystemPath PWD;
069:
070: private static boolean _isInitJNI;
071:
072: private Vfs() {
073: }
074:
075: /**
076: * Returns a new path relative to the current directory.
077: *
078: * @param url a relative or absolute url
079: * @return the new path.
080: */
081: public static Path lookup(String url) {
082: Path pwd = getPwd();
083:
084: if (!url.startsWith("/"))
085: return pwd.lookup(url, null);
086: else
087: return PWD.lookup(url, null);
088: }
089:
090: public static FilesystemPath getGlobalPwd() {
091: return PWD;
092: }
093:
094: /**
095: * Returns a path for the current directory.
096: */
097: public static Path getPwd() {
098: Path pwd = ENV_PWD.get();
099:
100: if (pwd == null) {
101: if (PWD == null) {
102: /* JNI set later
103: PWD = JniFilePath.create();
104:
105: if (PWD == null)
106: PWD = new FilePath(null);
107: */
108: PWD = new FilePath(null);
109: }
110: pwd = PWD;
111: ENV_PWD.setGlobal(pwd);
112: }
113:
114: return pwd;
115: }
116:
117: public static SchemeMap getLocalScheme() {
118: synchronized (_localSchemeMap) {
119: SchemeMap map = _localSchemeMap.getLevel();
120:
121: if (map == null) {
122: map = _localSchemeMap.get().copy();
123:
124: if (map == null)
125: map = DEFAULT_SCHEME_MAP.copy();
126:
127: _localSchemeMap.set(map);
128: }
129:
130: return map;
131: }
132: }
133:
134: /**
135: * Returns a path for the current directory.
136: */
137: public static Path getPwd(ClassLoader loader) {
138: return ENV_PWD.get(loader);
139: }
140:
141: /**
142: * Sets a path for the current directory in the current environment.
143: */
144: public static void setPwd(Path pwd) {
145: setPwd(pwd, Thread.currentThread().getContextClassLoader());
146: }
147:
148: /**
149: * Sets a path for the current directory in the current environment.
150: */
151: public static void setPwd(Path pwd, ClassLoader loader) {
152: ENV_PWD.set(pwd, loader);
153: }
154:
155: /**
156: * Returns a path for the current directory.
157: */
158: public static Path lookup() {
159: return getPwd();
160: }
161:
162: /**
163: * Returns a new path, including attributes.
164: * <p>For example, an application may want to set locale headers
165: * for an HTTP request.
166: *
167: * @param url the relative url
168: * @param attr attributes used in searching for the url
169: */
170: public static Path lookup(String url, Map<String, Object> attr) {
171: return getPwd().lookup(url, attr);
172: }
173:
174: /**
175: * Returns a path using the native filesystem conventions.
176: * <p>For example, on windows
177: *
178: * <code><pre>
179: * Path path = Vfs.lookup("d:\\temp\\test.html");
180: * </pre></code>
181: *
182: * @param url a relative path using the native filesystem conventions.
183: */
184: public static Path lookupNative(String url) {
185: return getPwd().lookupNative(url, null);
186: }
187:
188: /**
189: * Returns a native filesystem path with attributes.
190: *
191: * @param url a relative path using the native filesystem conventions.
192: * @param attr attributes used in searching for the url
193: */
194: public static Path lookupNative(String url, Map<String, Object> attr) {
195: return getPwd().lookupNative(url, attr);
196: }
197:
198: public static ReadWritePair openReadWrite(InputStream is,
199: OutputStream os) {
200: VfsStream s = new VfsStream(is, os);
201: WriteStream writeStream = new WriteStream(s);
202: ReadStream readStream = new ReadStream(s, writeStream);
203: return new ReadWritePair(readStream, writeStream);
204: }
205:
206: /**
207: * Creates new ReadStream from an InputStream
208: */
209: public static ReadStream openRead(InputStream is) {
210: if (is instanceof ReadStream)
211: return (ReadStream) is;
212:
213: VfsStream s = new VfsStream(is, null);
214: return new ReadStream(s);
215: }
216:
217: public static ReadStream openRead(InputStream is, WriteStream ws) {
218: VfsStream s = new VfsStream(is, null);
219: return new ReadStream(s, ws);
220: }
221:
222: /**
223: * Creates a ReadStream from a Reader
224: */
225: public static ReadStream openRead(Reader reader) {
226: if (reader instanceof ReadStream.StreamReader)
227: return ((ReadStream.StreamReader) reader).getStream();
228:
229: ReaderWriterStream s = new ReaderWriterStream(reader, null);
230: ReadStream is = new ReadStream(s);
231: try {
232: is.setEncoding("utf-8");
233: } catch (Exception e) {
234: }
235:
236: return is;
237: }
238:
239: /**
240: * Create a ReadStream from a string. utf-8 is used as the encoding
241: */
242: public static ReadStream openRead(String path) throws IOException {
243: return Vfs.lookup(path).openRead();
244: }
245:
246: public static ReadStream openString(String string) {
247: return com.caucho.vfs.StringReader.open(string);
248: }
249:
250: public static WriteStream openWrite(OutputStream os) {
251: if (os instanceof WriteStream)
252: return ((WriteStream) os);
253:
254: VfsStream s = new VfsStream(null, os);
255: return new WriteStream(s);
256: }
257:
258: public static WriteStream openWrite(Writer writer) {
259: ReaderWriterStream s = new ReaderWriterStream(null, writer);
260: WriteStream os = new WriteStream(s);
261:
262: try {
263: os.setEncoding("utf-8");
264: } catch (Exception e) {
265: }
266:
267: return os;
268: }
269:
270: /**
271: * Creates a write stream to a CharBuffer. This is the standard way
272: * to write to a string.
273: */
274: public static WriteStream openWrite(CharBuffer cb) {
275: com.caucho.vfs.StringWriter s = new com.caucho.vfs.StringWriter(
276: cb);
277: WriteStream os = new WriteStream(s);
278:
279: try {
280: os.setEncoding("utf-8");
281: } catch (Exception e) {
282: }
283:
284: return os;
285: }
286:
287: public static WriteStream openWrite(String path) throws IOException {
288: return lookup(path).openWrite();
289: }
290:
291: public static WriteStream openAppend(String path)
292: throws IOException {
293: return lookup(path).openAppend();
294: }
295:
296: /**
297: * Initialize the JNI.
298: */
299: public static void initJNI() {
300: if (_isInitJNI)
301: return;
302: _isInitJNI = true;
303:
304: // order matters because of static init and license checking
305: FilesystemPath jniFilePath = JniFilePath.create();
306:
307: if (jniFilePath != null) {
308: DEFAULT_SCHEME_MAP.put("file", jniFilePath);
309:
310: SchemeMap localMap = _localSchemeMap.get();
311: if (localMap != null)
312: localMap.put("file", jniFilePath);
313:
314: localMap = _localSchemeMap.get(ClassLoader
315: .getSystemClassLoader());
316: if (localMap != null)
317: localMap.put("file", jniFilePath);
318:
319: Vfs.PWD = jniFilePath;
320: Vfs.setPwd(jniFilePath);
321: }
322: }
323:
324: static {
325: DEFAULT_SCHEME_MAP = new SchemeMap();
326:
327: Path.setDefaultSchemeMap(DEFAULT_SCHEME_MAP);
328:
329: FilePath pwd = new FilePath(null);
330: PWD = pwd;
331: setPwd(pwd);
332: ENV_PWD.setGlobal(pwd);
333: ENV_PWD.set(pwd);
334:
335: _localSchemeMap.setGlobal(DEFAULT_SCHEME_MAP);
336:
337: DEFAULT_SCHEME_MAP.put("file", pwd);
338:
339: DEFAULT_SCHEME_MAP.put("memory", new MemoryScheme());
340:
341: DEFAULT_SCHEME_MAP.put("jar", new JarScheme(null));
342: DEFAULT_SCHEME_MAP.put("mailto", new MailtoPath(null, null,
343: null, null));
344: DEFAULT_SCHEME_MAP.put("classpath", new ClasspathPath(null, "",
345: ""));
346: DEFAULT_SCHEME_MAP.put("http", new HttpPath("127.0.0.1", 0));
347: DEFAULT_SCHEME_MAP.put("https", new HttpsPath("127.0.0.1", 0));
348: DEFAULT_SCHEME_MAP.put("hmux", new HmuxPath("127.0.0.1", 0));
349: DEFAULT_SCHEME_MAP.put("tcp", new TcpPath(null, null, null,
350: "127.0.0.1", 0));
351: DEFAULT_SCHEME_MAP.put("tcps", new TcpsPath(null, null, null,
352: "127.0.0.1", 0));
353: // DEFAULT_SCHEME_MAP.put("log", new LogPath(null, "/", null, "/"));
354: DEFAULT_SCHEME_MAP.put("merge", new MergePath());
355:
356: StreamImpl stdout = StdoutStream.create();
357: StreamImpl stderr = StderrStream.create();
358: DEFAULT_SCHEME_MAP.put("stdout", stdout.getPath());
359: DEFAULT_SCHEME_MAP.put("stderr", stderr.getPath());
360: VfsStream nullStream = new VfsStream(null, null);
361: DEFAULT_SCHEME_MAP.put("null", new ConstPath(null, nullStream));
362: DEFAULT_SCHEME_MAP.put("jndi", new JndiPath());
363:
364: DEFAULT_SCHEME_MAP.put("config", new ConfigPath());
365: DEFAULT_SCHEME_MAP.put("spy", new SpyScheme());
366:
367: }
368: }
|