001: /*
002: * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
003: * PROPRIETARY/CONFIDENTIAL. Use of this product is subject to license terms.
004: */
005:
006: //
007: package com.sun.portal.ffj.filesystems;
008:
009: import java.beans.PropertyVetoException;
010:
011: import java.io.File;
012: import java.io.IOException;
013: import java.io.FileNotFoundException;
014: import java.io.InputStream;
015: import java.io.OutputStream;
016: import java.io.FileInputStream;
017: import java.io.FileOutputStream;
018: import java.io.InputStreamReader;
019: import java.io.BufferedReader;
020: import java.io.PrintWriter;
021: import java.io.FileWriter;
022:
023: import java.net.URL;
024:
025: import java.util.Date;
026:
027: import org.openide.TopManager;
028: import org.openide.ErrorManager;
029: import org.openide.NotifyDescriptor;
030:
031: import org.openide.filesystems.FileSystem;
032: import org.openide.filesystems.FileObject;
033: import org.openide.filesystems.Repository;
034: import org.openide.filesystems.DefaultAttributes;
035: import org.openide.filesystems.LocalFileSystem;
036: import org.openide.filesystems.FileSystemCapability;
037: import org.openide.filesystems.FileStateInvalidException;
038: import org.openide.filesystems.FileUtil;
039:
040: import org.openide.util.NbBundle;
041:
042: import com.sun.portal.ffj.util.PSConstants;
043: import com.sun.portal.ffj.util.FileOverwriteDialog;
044:
045: public class PSFileSystem extends LocalFileSystem implements
046: PSConstants {
047:
048: private static final int REFRESH_TIME = 15000; // 15 seconds
049: private File rootFile = new File(".");
050: private boolean readOnly;
051:
052: //
053: //
054: //
055: public PSFileSystem() {
056: // Create and use implementations of file system functionality:
057: info = new InfoImpl();
058: change = new ChangeImpl();
059:
060: // Handle filesystem.attributes files normally:
061: DefaultAttributes defattr = new DefaultAttributes(info, change,
062: new ListImpl());
063: // (Otherwise set attr to a special implementation, and use ListImpl for list.)
064: attr = defattr;
065: list = defattr;
066:
067: // See below:
068: // transfer = new TransferImpl();
069:
070: //
071: setRefreshTime(REFRESH_TIME);
072: }
073:
074: public PSFileSystem(FileSystemCapability cap) {
075: this ();
076: setCapability(cap);
077: }
078:
079: // --------- NAMING AND PROPERTIES ---------
080:
081: // This should be something unique based on the filesystem's config:
082: protected String computeSystemName(File rootFile) {
083: return systemNameFromRoot(rootFile);
084: }
085:
086: private static String systemNameFromRoot(File rootFile) {
087: String fsName = PS_FILESYSTEM_NAME;
088: String fsNameFromResources = NbBundle.getMessage(
089: PSFileSystem.class, "PS_Filesystem_Name");
090: if (fsNameFromResources != null)
091: fsName = fsNameFromResources;
092: return fsName + "[" + rootFile.toString() + "]";
093: }
094:
095: // As displayed to the user:
096: public String getDisplayName() {
097: if (!isValid())
098: return NbBundle.getMessage(PSFileSystem.class,
099: "LAB_invalid_file_system", rootFile.toString());
100: else
101: return NbBundle.getMessage(PSFileSystem.class,
102: "LAB_valid_file_system", rootFile.toString());
103: }
104:
105: // Bean getter.
106: public File getRootDirectory() {
107: return rootFile;
108: }
109:
110: // Bean setter. Changing the root directory (or in general, the identity
111: // of the root file object) should cause everything using this filesystem
112: // to refresh. The system name must change and refreshRoot should be used
113: // to ensure that everything is correctly updated.
114: public synchronized void setRootDirectory(File r)
115: throws PropertyVetoException, IOException {
116: //
117: if (!r.exists() || r.isFile())
118: throw new PSFileSystemException(r.toString()
119: + " does not exist", NbBundle.getMessage(
120: PSFileSystem.class, "EXC_root_dir_does_not_exist",
121: r.toString()));
122:
123: setSystemName(computeSystemName(r));
124: rootFile = r;
125: firePropertyChange(PROP_ROOT, null, refreshRoot());
126: }
127:
128: // Bean getter.
129: public boolean isReadOnly() {
130: return readOnly;
131: }
132:
133: // Bean setter.
134: public void setReadOnly(boolean flag) {
135: if (flag != readOnly) {
136: readOnly = flag;
137: firePropertyChange(PROP_READ_ONLY, new Boolean(!flag),
138: new Boolean(flag));
139: }
140: }
141:
142: // ----------- SPECIAL CAPABILITIES --------------
143:
144: // This is how you can affect the classpath for execution, compilation, etc.:
145: public void prepareEnvironment(FileSystem.Environment environment) {
146: environment.addClassPath(rootFile.toString());
147: }
148:
149: // ----------- IMPLEMENTATIONS OF ABSTRACT FUNCTIONALITY ----------
150:
151: // Utility method only:
152: private File getFile(String name) {
153: return new File(rootFile, name);
154: }
155:
156: // Information about files and operations on the contents which do
157: // not affect the file's presence or name.
158: private class InfoImpl implements Info {
159: //
160: //
161: //
162: public boolean folder(String name) {
163: return getFile(name).isDirectory();
164: }
165:
166: public Date lastModified(String name) {
167: return new Date(getFile(name).lastModified());
168: }
169:
170: public boolean readOnly(String name) {
171: File f = getFile(name);
172: return f.exists() && !f.canWrite();
173: }
174:
175: public String mimeType(String name) {
176: // Unless you have some special means of determining MIME type
177: // (e.g. HTTP headers), ask IDE to use its normal heuristics:
178: // the MIME resolver pool and then file extensions, or if nothing
179: // matches, just content/unknown.
180: return null;
181: }
182:
183: public long size(String name) {
184: return getFile(name).length();
185: }
186:
187: public InputStream inputStream(String name)
188: throws FileNotFoundException {
189: return new FileInputStream(getFile(name));
190: }
191:
192: public OutputStream outputStream(String name)
193: throws IOException {
194: return new FileOutputStream(getFile(name));
195: }
196:
197: // AbstractFileSystem handles locking the file to the rest of the IDE.
198: // This only means that you should define how the file should be locked
199: // to the outside world--perhaps it does not need to be.
200: public void lock(String name) throws IOException {
201: File file = getFile(name);
202:
203: if (file.exists() && !file.canWrite())
204: throw new PSFileSystemException("file " + file
205: + " could not be locked", NbBundle.getMessage(
206: PSFileSystem.class,
207: "EXC_file_could_not_be_locked", file.getName(),
208: getDisplayName(), file.getPath()));
209: }
210:
211: public void unlock(String name) {
212: // Nothing special needed to unlock a file to the outside world.
213: }
214:
215: public void markUnimportant(String name) {
216: // Do nothing special. Version-control systems may use this to mark
217: // certain files (e.g. *.class) as not needing to be stored in the VCS
218: // while others (source files) are by default important.
219: }
220:
221: //
222: //
223: //
224: }
225:
226: // Operations that change the available files.
227: private class ChangeImpl implements Change {
228: //
229: //
230: //
231: public void createFolder(String name) throws IOException {
232: File f = getFile(name);
233: Object[] errorParams = new Object[] { f.getName(),
234: getDisplayName(), f.getPath() };
235:
236: if (name.equals(""))
237: throw new PSFileSystemException(
238: "cannot create empty name", NbBundle
239: .getMessage(PSFileSystem.class,
240: "EXC_create_empty_name",
241: errorParams));
242:
243: if (f.exists())
244: throw new PSFileSystemException("folder " + f
245: + " already exists", NbBundle.getMessage(
246: PSFileSystem.class,
247: "EXC_folder_already_exists", errorParams));
248:
249: boolean b = createRecursiveFolder(f);
250: if (!b)
251: throw new PSFileSystemException("folder " + f
252: + " could not be created", NbBundle.getMessage(
253: PSFileSystem.class,
254: "EXC_folder_could_not_be_created", errorParams));
255:
256: }
257:
258: private boolean createRecursiveFolder(File f) {
259: if (f.exists())
260: return true;
261:
262: if (!f.isAbsolute())
263: f = f.getAbsoluteFile();
264:
265: String par = f.getParent();
266: if (par == null)
267: return false;
268:
269: if (!createRecursiveFolder(new File(par)))
270: return false;
271:
272: f.mkdir();
273: return f.exists();
274: }
275:
276: public void createData(String name) throws IOException {
277: File f = getFile(name);
278:
279: if (!f.createNewFile())
280: throw new PSFileSystemException("file " + f
281: + " could not be created", NbBundle.getMessage(
282: PSFileSystem.class,
283: "EXC_file_could_not_be_created", f.getName(),
284: getDisplayName(), f.getPath()));
285: }
286:
287: public void rename(String oldName, String newName)
288: throws IOException {
289: File of = getFile(oldName);
290: File nf = getFile(newName);
291:
292: if (!of.renameTo(nf))
293: throw new PSFileSystemException("file " + of
294: + " could not be renamed to " + nf, NbBundle
295: .getMessage(PSFileSystem.class,
296: "EXC_file_could_not_be_renamed",
297: new Object[] { of.getName(),
298: nf.getName(), getDisplayName(),
299: of.getPath(), nf.getPath() }));
300: }
301:
302: public void delete(String name) throws IOException {
303: File file = getFile(name);
304:
305: if (file.exists() && !deleteFile(file))
306: throw new PSFileSystemException("file " + file
307: + " could not be deleted", NbBundle.getMessage(
308: PSFileSystem.class,
309: "EXC_file_could_not_be_deleted",
310: file.getName(), getDisplayName(), file
311: .getPath()));
312: }
313:
314: private boolean deleteFile(File file) {
315: if (file.isDirectory()) {
316: File[] arr = file.listFiles();
317: for (int i = 0; i < arr.length; i++)
318: if (!deleteFile(arr[i]))
319: return false;
320: }
321: return file.delete();
322: }
323:
324: //
325: //
326: //
327: }
328:
329: // Operation which provides the directory structure.
330: private class ListImpl implements List {
331:
332: public String[] children(String name) {
333: File f = getFile(name);
334: if (f.isDirectory()) {
335: return f.list();
336: } else {
337: return null;
338: }
339: }
340: }
341:
342: private static void assureContents(File rootDir) throws IOException {
343: //
344: String method = "assureContents: ";
345: System.out.println(method + "Entry");
346:
347: // Get default filesystem from layer XML.
348:
349: Repository repo = TopManager.getDefault().getRepository();
350: FileSystem defaultFS = repo.getDefaultFileSystem();
351: FileObject fromtop = defaultFS.find(PS_DEFAULT_FS_NAME, null,
352: null);
353: copyChildren(fromtop, rootDir, FileOverwriteDialog.SKIP);
354:
355: // psrun.jar needs to be copied from external library.
356: // This one is a stream copy, since it is a binary jar file.
357:
358: File jf = PSFSInstall.getPSJarFile();
359: File lf = new File(rootDir, "WEB-INF" + File.separator
360: + "lib/psrun.jar");
361:
362: if (jf.exists() && !lf.exists()) {
363: lf.getParentFile().mkdirs();
364: FileInputStream is = new FileInputStream(jf);
365: FileOutputStream os = new FileOutputStream(lf);
366: byte buf[] = new byte[8000];
367: for (;;) {
368: int len = is.read(buf);
369: if (len < 0) {
370: break;
371: }
372: os.write(buf, 0, len);
373: }
374:
375: os.flush();
376: os.close();
377: }
378:
379: // At least copy the common library stuff for tomcat.
380:
381: File commondir = new File(rootDir, "WEB-INF" + File.separator
382: + "common");
383: if (commondir.exists()) {
384: String homeDir = System.getProperty("netbeans.home");
385: String message = "COMLIB_Tomcat_OK";
386: int mtype = NotifyDescriptor.INFORMATION_MESSAGE;
387: if (homeDir == null) {
388: homeDir = ".";
389: }
390: File tcdir = new File(homeDir, "tomcat401/common/lib");
391: if (!tcdir.exists()) {
392: tcdir = new File(homeDir, "jwsdp/common/lib");
393: }
394: int libcount = 0;
395: try {
396: libcount = copyTomcatChildren(commondir, tcdir);
397: } catch (Exception ex) {
398: message = "COMLIB_Tomcat_Failed";
399: mtype = NotifyDescriptor.ERROR_MESSAGE;
400: }
401:
402: if (libcount > 0) {
403: String mp[] = { commondir.getPath(), tcdir.getPath() };
404: message = NbBundle.getMessage(PSFileSystem.class,
405: message, mp);
406: NotifyDescriptor d = new NotifyDescriptor.Message(
407: message, mtype);
408: TopManager.getDefault().notify(d);
409: }
410: }
411: }
412:
413: private static int copyChildren(FileObject from, File todir,
414: int ifex) throws IOException {
415: FileObject ch[] = from.getChildren();
416: for (int i = 0; i < ch.length; ++i) {
417: if (ch[i].isFolder()) {
418: File dir = new File(todir, ch[i].getName());
419: dir.mkdirs();
420: ifex = copyChildren(ch[i], dir, ifex);
421: continue;
422: }
423:
424: // Create new file. For text types, use a reader and copy with a
425: // printwriter to conform to local filesystem notion of a newline.
426: // Currently, we recognize "jar" as a binary type.
427:
428: String nm = ch[i].getNameExt();
429: File to = new File(todir, nm);
430:
431: if (to.exists()) {
432: if (ifex != FileOverwriteDialog.SKIP_ALL
433: && ifex != FileOverwriteDialog.OVERWRITE_ALL) {
434: FileOverwriteDialog fod = new FileOverwriteDialog(
435: null, true, todir.getPath(), nm, ifex);
436: fod.show();
437: ifex = fod.getOverwriteChoice();
438: }
439: if (ifex == FileOverwriteDialog.SKIP
440: || ifex == FileOverwriteDialog.SKIP_ALL) {
441: continue;
442: }
443: }
444:
445: URL url = ch[i].getURL();
446: String ext = ch[i].getExt();
447:
448: if (ext.equals("jar")) {
449: binaryCopy(url, to);
450: } else {
451: textCopy(url, to);
452: }
453: }
454:
455: return ifex;
456: }
457:
458: // Tomcat files - no interaction.
459:
460: private static int copyTomcatChildren(File from, File todir)
461: throws IOException {
462: File ch[] = from.listFiles();
463: int count = 0;
464:
465: for (int i = 0; i < ch.length; ++i) {
466:
467: File to = new File(todir, ch[i].getName());
468: if (to.exists()) {
469: continue;
470: }
471:
472: if (ch[i].isDirectory()) {
473: to.mkdirs();
474: count += copyTomcatChildren(ch[i], to);
475: continue;
476: }
477:
478: ++count;
479: URL url = ch[i].toURL();
480:
481: if (ch[i].getName().endsWith("jar")) {
482: binaryCopy(url, to);
483: } else {
484: textCopy(url, to);
485: }
486: }
487:
488: return count;
489: }
490:
491: private static void textCopy(URL url, File to) throws IOException {
492:
493: InputStreamReader isr = new InputStreamReader((InputStream) url
494: .getContent());
495: BufferedReader br = new BufferedReader(isr);
496: PrintWriter pw = new PrintWriter(new FileWriter(to));
497:
498: for (;;) {
499: String s = br.readLine();
500: if (s == null)
501: break;
502: pw.println(s);
503: }
504:
505: pw.flush();
506: pw.close();
507: }
508:
509: private static void binaryCopy(URL url, File to) throws IOException {
510:
511: InputStream is = (InputStream) url.getContent();
512: OutputStream os = new FileOutputStream(to);
513:
514: byte buf[] = new byte[2400];
515: int len;
516: while ((len = is.read(buf)) > 0) {
517: os.write(buf, 0, len);
518: }
519:
520: os.flush();
521: os.close();
522: }
523:
524: private static PSFileSystem create() throws IOException,
525: PropertyVetoException {
526:
527: String message = NbBundle.getMessage(PSFileSystem.class,
528: "PS_Mounting");
529: NotifyDescriptor d = new NotifyDescriptor.Message(message,
530: NotifyDescriptor.INFORMATION_MESSAGE);
531: TopManager.getDefault().notify(d);
532:
533: // Create root directory
534:
535: String rootPath = getRootPath();
536: File rootDir = new File(rootPath);
537: rootDir.mkdirs();
538:
539: // Make sure that configuration files are present
540:
541: assureContents(rootDir);
542:
543: // Create filesystem
544:
545: PSFileSystem psFS = new PSFileSystem();
546: psFS.setRootDirectory(rootDir);
547: TopManager.getDefault().getRepository().addFileSystem(psFS);
548: PSRuntimeJarFS.mount();
549: PortletJarFS.mount();
550: PSFSInstall.postCreate();
551:
552: return psFS;
553: }
554:
555: //
556: //
557: //
558: public static String getRootPath() {
559: String rootPath = null;
560:
561: // Get FFJ user directory
562: String userDir = System.getProperty("netbeans.user");
563: if (userDir == null)
564: userDir = ".";
565:
566: rootPath = userDir + File.separator
567: + PS_FILESYSTEM_BASEDIR_NAME;
568:
569: //
570: return rootPath;
571: }
572:
573: // Return absolute path for a FileObject.
574: public static String getAbsolutePathName(FileObject fo) {
575: //
576: String method = "getAbsolutePathName: ";
577: String retVal = null;
578:
579: try {
580: //
581: String relativePathName = fo.getPackageNameExt(
582: File.separatorChar, PS_EXT_SEPARATOR.charAt(0));
583: FileSystem fs = fo.getFileSystem();
584:
585: if (fs instanceof LocalFileSystem) {
586: File root = ((LocalFileSystem) fs).getRootDirectory();
587: retVal = root.getAbsolutePath() + File.separator
588: + relativePathName;
589: } else {
590: File root = FileUtil.toFile(fs.getRoot());
591: retVal = root.getAbsolutePath() + File.separator
592: + relativePathName;
593: }
594: } catch (FileStateInvalidException fsie) {
595: TopManager.getDefault().getErrorManager().notify(
596: ErrorManager.USER, fsie);
597: }
598:
599: return retVal;
600: }
601:
602: public static PSFileSystem getPSFilesystem(boolean create) {
603: PSFileSystem fs = (PSFileSystem) TopManager.getDefault()
604: .getRepository().findFileSystem(
605: systemNameFromRoot(new File(getRootPath())));
606: try {
607: if (fs == null && create)
608: fs = create();
609: } catch (Exception e) {
610: TopManager.getDefault().getErrorManager().notify(
611: ErrorManager.USER, e);
612: fs = null;
613: }
614:
615: return fs;
616: }
617:
618: //
619: //
620: //
621: public FileObject getPSSimulator() {
622: return find(".", PS_SIMULATOR_FILENAME, PS_SIMULATOR_FILEEXT);
623: }
624:
625: public FileObject getPSPackager() {
626: return find(".", PS_PACKAGER_FILENAME, PS_PACKAGER_FILEEXT);
627: }
628: }
|