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: package com.sun.portal.harness;
007:
008: import java.util.Vector;
009: import java.util.StringTokenizer;
010: import java.util.HashMap;
011: import java.util.Iterator;
012:
013: import java.io.Serializable;
014: import java.io.File;
015: import java.io.FileInputStream;
016: import java.io.InputStream;
017:
018: import javax.servlet.http.HttpServletRequest;
019: import javax.servlet.http.HttpServletResponse;
020: import javax.servlet.http.HttpSession;
021:
022: import javax.servlet.http.HttpSessionBindingListener;
023: import javax.servlet.http.HttpSessionBindingEvent;
024:
025: import javax.servlet.jsp.PageContext;
026:
027: import org.w3c.dom.Document;
028: import org.w3c.dom.Element;
029: import org.w3c.dom.Node;
030: import org.w3c.dom.NodeList;
031: import org.w3c.dom.Text;
032:
033: import javax.xml.parsers.DocumentBuilder;
034: import javax.xml.parsers.DocumentBuilderFactory;
035:
036: import com.sun.portal.desktop.ServletConfigThreadLocalizer;
037: import com.sun.portal.desktop.ServletContextThreadLocalizer;
038:
039: import com.sun.portal.desktop.deployment.Par;
040: import com.sun.portal.desktop.deployment.ProviderPackageFile;
041: import com.sun.portal.desktop.deployment.ClassPPF;
042: import com.sun.portal.desktop.deployment.ParFileException;
043: import com.sun.portal.desktop.deployment.ParManifest;
044: import com.sun.portal.desktop.deployment.StaticPPF;
045: import com.sun.portal.desktop.deployment.PropLocPPF;
046: import com.sun.portal.desktop.deployment.ExtractOp;
047: import com.sun.portal.desktop.deployment.ParFileBuilder;
048:
049: public class Packager implements HttpSessionBindingListener,
050: Serializable {
051:
052: // URL arguments which may be constructed by external entry points to the packager
053:
054: public static final String ARG_COMPFILE = ProviderHarness.ARG_COMPFILE;
055: public static final String ARG_CONFIGDIR = ProviderHarness.ARG_CONFIGDIR;
056: public static final String ARG_DOCROOT = ProviderHarness.ARG_DOCROOT;
057: public static final String ARG_PARFILE = ProviderHarness.ARG_PARFILE;
058: public static final String ARG_DESKTOP_XFER = ProviderHarness.ARG_DESKTOP_XFER;
059:
060: // Visible to the packager jsp.
061:
062: public static final String ARG_OPERATION = "OPERATION";
063: public static final String ARG_PROVIDER_ACTIVE = "PV_ACTIVE";
064: public static final String ARG_PROVIDER_NAME = "PV_NAME";
065: public static final String ARG_CHANNEL_ACTIVE = "CH_ACTIVE";
066: public static final String ARG_CHANNEL_NAME = "CH_NAME";
067: public static final String ARG_PROVIDER_CLASSES = "PV_CLASSES";
068: public static final String ARG_PROVIDER_STATICFILES = "PV_STATF";
069: public static final String ARG_PROVIDER_PBFILES = "PV_PBF";
070: public static final String ARG_CHANNEL_CLASSES = "CH_CLASSES";
071: public static final String ARG_CHANNEL_STATICFILES = "CH_STATF";
072: public static final String ARG_CHANNEL_PBFILES = "CH_PBF";
073:
074: public static final String ARG_OPCREATE = "create";
075: public static final String ARG_SETACTIVE = "active";
076: public static final String ARG_SETINACTIVE = "inactive";
077:
078: private Packager() {
079: m_ConfigDir = ProviderHarness.defaultConfigDir();
080: m_DocRoot = defaultDocRoot();
081: }
082:
083: static public Packager getPackager(HttpServletRequest req,
084: HttpServletResponse resp, PageContext pctx)
085: throws ProviderHarnessException {
086:
087: HttpSession sess = req.getSession();
088: String cf = req.getParameter(ARG_COMPFILE);
089: Packager pkg;
090:
091: ServletConfigThreadLocalizer.set(pctx.getServletConfig());
092: ServletContextThreadLocalizer.set(pctx.getServletConfig()
093: .getServletContext());
094:
095: if (cf == null) {
096: pkg = (Packager) sess.getAttribute(SESSION_KEY);
097: if (pkg == null) {
098: throw new ProviderHarnessException(
099: "Cannot find Packager in Session");
100: }
101:
102: pkg.restore(req, resp, pctx);
103: return pkg;
104: }
105:
106: pkg = new Packager();
107: sess.setAttribute(SESSION_KEY, pkg);
108:
109: pkg.init(cf, req, resp, pctx);
110: return pkg;
111: }
112:
113: public String getOutputFile() {
114: return m_ParFile;
115: }
116:
117: public String getCompFile() {
118: return m_CompFile;
119: }
120:
121: public String getDocRoot() {
122: return m_DocRoot;
123: }
124:
125: public String getProviderName() {
126: return m_ProviderName;
127: }
128:
129: public String getChannelName() {
130: return m_ChannelName;
131: }
132:
133: public boolean isChannelActive() {
134: return m_ChannelActive;
135: }
136:
137: public boolean isProviderActive() {
138: return m_ProviderActive;
139: }
140:
141: public boolean isChannelPresent() {
142: return m_HaveChannel;
143: }
144:
145: public boolean isProviderPresent() {
146: return m_HaveProvider;
147: }
148:
149: public String getMessage() {
150: return m_Message;
151: }
152:
153: public String getErrorMessage() {
154: return m_ErrorMessage;
155: }
156:
157: public String getProviderClasses() {
158: return m_ProviderClasses;
159: }
160:
161: public String getProviderPBFiles() {
162: return m_ProviderPBFiles;
163: }
164:
165: public String getProviderStaticFiles() {
166: return m_ProviderStaticFiles;
167: }
168:
169: public String getChannelClasses() {
170: return m_ChannelClasses;
171: }
172:
173: public String getChannelPBFiles() {
174: return m_ChannelPBFiles;
175: }
176:
177: public String getChannelStaticFiles() {
178: return m_ChannelStaticFiles;
179: }
180:
181: public void valueUnbound(
182: HttpSessionBindingEvent httpSessionBindingEvent) {
183: if (!m_IgnoreClear) {
184: try {
185: clear();
186: } catch (Exception ex) {
187: System.out
188: .println("!!!! EXCEPTION WHILE UNBINDING PACKAGER: "
189: + ex.getMessage());
190: }
191: }
192: }
193:
194: public void valueBound(
195: HttpSessionBindingEvent httpSessionBindingEvent) {
196: }
197:
198: private void init(String cfile, HttpServletRequest req,
199: HttpServletResponse resp, PageContext pctx)
200: throws ProviderHarnessException {
201:
202: initTransients(req, resp, pctx);
203:
204: String cfgdir = req.getParameter(ARG_CONFIGDIR);
205: if (cfgdir != null) {
206: m_ConfigDir = cfgdir;
207: }
208:
209: String dxfer = req.getParameter(ARG_DESKTOP_XFER);
210: if (dxfer != null) {
211: HarnessProviderContext.transferDesktop(dxfer, m_ConfigDir);
212: }
213:
214: m_CompFile = cfile;
215:
216: String pfile = req.getParameter(ARG_PARFILE);
217: if (pfile != null) {
218: m_ParFile = pfile;
219: } else {
220: int idx = cfile.lastIndexOf('.');
221: if (idx > 0) {
222: m_ParFile = cfile.substring(0, idx) + ".par";
223: }
224: }
225:
226: String droot = req.getParameter(ARG_DOCROOT);
227: if (droot != null) {
228: m_DocRoot = droot;
229: }
230:
231: Document doc = makeDocument();
232: m_HaveChannel = haveChannel(doc);
233: m_HaveProvider = haveProvider(doc);
234:
235: m_ChannelName = null;
236: m_ProviderName = null;
237: m_ProviderImpClass = "";
238:
239: try {
240: if (m_HaveChannel) {
241: m_ChannelName = Par.getChannelName(doc);
242: m_ProviderName = Par.getProviderNameFromChannel(doc);
243: }
244: if (m_HaveProvider) {
245: m_ProviderName = Par.getProviderName(doc);
246: m_ProviderImpClass = Par.getProviderClass(doc);
247: }
248: } catch (Exception ex) {
249: throw new ProviderHarnessException(ex.getMessage());
250: }
251:
252: m_ProviderClasses = m_ProviderImpClass;
253: m_ProviderPBFiles = "";
254: m_ProviderStaticFiles = "";
255: m_ChannelClasses = "";
256: m_ChannelPBFiles = ".";
257: m_ChannelStaticFiles = "";
258:
259: m_ProviderActive = m_HaveProvider;
260: m_ChannelActive = m_HaveChannel;
261:
262: refreshSelfInSession();
263: }
264:
265: private Document makeDocument() throws ProviderHarnessException {
266:
267: DocumentBuilder db = null;
268: try {
269: DocumentBuilderFactory dbf = DocumentBuilderFactory
270: .newInstance();
271: db = dbf.newDocumentBuilder();
272: } catch (Exception ex) {
273: throw new ProviderHarnessException(
274: "Failure creating document builder", ex);
275: }
276:
277: Document doc = null;
278: try {
279: db.setEntityResolver(new ParEntryEntityResolver());
280: doc = db.parse(new FileInputStream(m_CompFile));
281: } catch (Exception ex) {
282: throw new ProviderHarnessException(
283: "Failure reading component xml - " + m_CompFile, ex);
284: }
285:
286: return doc;
287: }
288:
289: private void restore(HttpServletRequest req,
290: HttpServletResponse resp, PageContext pctx)
291: throws ProviderHarnessException {
292: initTransients(req, resp, pctx);
293: processOperations(req);
294: refreshSelfInSession();
295: }
296:
297: private void clear() throws ProviderHarnessException {
298: }
299:
300: private void initTransients(HttpServletRequest req,
301: HttpServletResponse resp, PageContext pctx) {
302: m_Request = req;
303: m_Response = resp;
304: m_PageContext = pctx;
305: m_Message = null;
306: m_ErrorMessage = null;
307: }
308:
309: private void processOperations(HttpServletRequest req)
310: throws ProviderHarnessException {
311: String op = req.getParameter(ARG_OPERATION);
312: if (op == null) {
313: return;
314: }
315:
316: if (op.equals(ARG_OPCREATE)) {
317: processFields(req);
318: try {
319: createFile();
320: m_Message = "Par file " + m_ParFile + " created.";
321: } catch (Exception ex) {
322: m_ErrorMessage = ex.toString();
323: }
324: return;
325: }
326:
327: throw new ProviderHarnessException("Unrecognized operation: "
328: + op);
329: }
330:
331: private void processFields(HttpServletRequest req) {
332: String val;
333:
334: val = req.getParameter(ARG_PARFILE);
335: if (val != null) {
336: m_ParFile = val;
337: }
338:
339: // These are intended to work with HTML checkboxes, so we have to assume
340: // that ABSENCE of the argument means FALSE - fooey!
341:
342: val = req.getParameter(ARG_PROVIDER_ACTIVE);
343: if (val != null && val.equals(ARG_SETACTIVE)) {
344: m_ProviderActive = true;
345: } else {
346: m_ProviderActive = false;
347: }
348:
349: val = req.getParameter(ARG_CHANNEL_ACTIVE);
350: if (val != null && val.equals(ARG_SETACTIVE)) {
351: m_ChannelActive = true;
352: } else {
353: m_ChannelActive = false;
354: }
355:
356: // The rest of the arguments can be interpreted so that
357: // "missing" means "leave alone"
358:
359: val = req.getParameter(ARG_PROVIDER_NAME);
360: if (val != null) {
361: m_ProviderName = val;
362: }
363:
364: val = req.getParameter(ARG_CHANNEL_NAME);
365: if (val != null) {
366: m_ChannelName = val;
367: }
368:
369: val = req.getParameter(ARG_PROVIDER_CLASSES);
370: if (val != null) {
371: m_ProviderClasses = val;
372: }
373:
374: val = req.getParameter(ARG_PROVIDER_STATICFILES);
375: if (val != null) {
376: m_ProviderStaticFiles = val;
377: }
378:
379: val = req.getParameter(ARG_PROVIDER_PBFILES);
380: if (val != null) {
381: m_ProviderPBFiles = val;
382: }
383:
384: val = req.getParameter(ARG_CHANNEL_CLASSES);
385: if (val != null) {
386: m_ChannelClasses = val;
387: }
388:
389: val = req.getParameter(ARG_CHANNEL_STATICFILES);
390: if (val != null) {
391: m_ChannelStaticFiles = val;
392: }
393:
394: val = req.getParameter(ARG_CHANNEL_PBFILES);
395: if (val != null) {
396: m_ChannelPBFiles = val;
397: }
398: }
399:
400: private void createFile() throws ProviderHarnessException {
401:
402: // Get the appropriately wrapped ParEntry document.
403:
404: Document doc = copyDoc(makeDocument());
405:
406: // Create a hashmap of all the ProviderPackageFiles. This takes care
407: // of files specified in both channel and provider lists.
408:
409: HashMap map = new HashMap();
410: PackagerProps pp = PackagerProps.makePackagerProps(
411: m_ChannelName, m_ConfigDir, m_CompFile);
412: m_ClassBase = pp.getPBFProperty("providerClassBaseDir");
413: addClassFiles(map, m_ProviderClasses, ExtractOp.TYPE_PROVIDER);
414: addClassFiles(map, m_ChannelClasses, ExtractOp.TYPE_CHANNEL);
415: addStaticFiles(map, m_ProviderStaticFiles,
416: ExtractOp.TYPE_PROVIDER);
417: addStaticFiles(map, m_ChannelStaticFiles,
418: ExtractOp.TYPE_CHANNEL);
419: addPBFiles(pp, map, m_ProviderPBFiles, ExtractOp.TYPE_PROVIDER);
420: addPBFiles(pp, map, m_ChannelPBFiles, ExtractOp.TYPE_CHANNEL);
421:
422: // Build a vector of our resultant files.
423:
424: Vector v = new Vector();
425: Iterator it = map.keySet().iterator();
426: while (it.hasNext()) {
427: PPF_Info pi = (PPF_Info) map.get(it.next());
428: v.add(pi.getPPF());
429: }
430:
431: // OK, make our par file.
432:
433: try {
434: ParFileBuilder pbf = new ParFileBuilder(false, System.out);
435: pbf.addDPEntry(doc, v);
436: pbf.makeParFile(m_ParFile);
437: } catch (Exception ex) {
438: throw new ProviderHarnessException(
439: "Error building par file", ex);
440: }
441: }
442:
443: // HACK - copyDoc() is a rather clumsy way of assuring that we get the
444: // right outer "wrapper" on the document we place in the par file.
445:
446: private Document copyDoc(Document doc)
447: throws ProviderHarnessException {
448:
449: Element top = doc.getDocumentElement();
450: Element chNode = null;
451: Element prNode = null;
452: String desc = null;
453: String name = top.getAttribute("name");
454:
455: NodeList kids = top.getChildNodes();
456: for (int i = 0; i < kids.getLength(); ++i) {
457: Node child = kids.item(i);
458: if (child instanceof Element) {
459: Element elt = (Element) child;
460: if (elt.getNodeName().equals("Channel")
461: && m_ChannelActive) {
462: chNode = elt;
463: elt.setAttribute("name", m_ChannelName);
464: elt.setAttribute("provider", m_ProviderName);
465: continue;
466: }
467: if (elt.getNodeName().equals("Provider")
468: && m_ProviderActive) {
469: prNode = elt;
470: elt.setAttribute("name", m_ProviderName);
471: continue;
472: }
473: if (elt.getNodeName().equals("Description")) {
474: StringBuffer buf = new StringBuffer();
475: NodeList dkids = elt.getChildNodes();
476: for (int j = 0; j < dkids.getLength(); ++j) {
477: Node dchild = dkids.item(i);
478: if (dchild instanceof Text) {
479: buf.append(dchild.getNodeValue());
480: }
481: }
482: desc = buf.toString();
483: }
484: }
485: }
486:
487: if (m_ChannelActive && chNode == null) {
488: throw new ProviderHarnessException(
489: "Channel was not specified in parentry document.");
490: }
491: if (m_ProviderActive && prNode == null) {
492: throw new ProviderHarnessException(
493: "Provider was not specified in parentry document.");
494: }
495:
496: try {
497: return Par.makeParEntry(name, desc, prNode, chNode);
498: } catch (Exception ex) {
499: throw new ProviderHarnessException(ex.getMessage());
500: }
501: }
502:
503: // Hack - these logically belong in the par utility
504:
505: private boolean haveChannel(Document doc) {
506: Element top = doc.getDocumentElement();
507: NodeList kids = top.getChildNodes();
508: for (int i = 0; i < kids.getLength(); ++i) {
509: Node child = kids.item(i);
510: if (child instanceof Element) {
511: Element elt = (Element) child;
512: if (elt.getNodeName().equals("Channel")) {
513: return true;
514: }
515: }
516: }
517:
518: return false;
519: }
520:
521: private boolean haveProvider(Document doc) {
522: Element top = doc.getDocumentElement();
523: NodeList kids = top.getChildNodes();
524: for (int i = 0; i < kids.getLength(); ++i) {
525: Node child = kids.item(i);
526: if (child instanceof Element) {
527: Element elt = (Element) child;
528: if (elt.getNodeName().equals("Provider")) {
529: return true;
530: }
531: }
532: }
533:
534: return false;
535: }
536:
537: private void addClassFiles(HashMap map, String list, int type) {
538: StringTokenizer toks = new StringTokenizer(list, " \t\r\n");
539: while (toks.hasMoreTokens()) {
540: checkAdd(map, new PPF_Info(toks.nextToken(), type));
541: }
542: }
543:
544: private void addStaticFiles(HashMap map, String list, int type) {
545: StringTokenizer toks = new StringTokenizer(list, "\r\n");
546: while (toks.hasMoreTokens()) {
547: StringTokenizer subtoks = new StringTokenizer(toks
548: .nextToken(), " \t");
549: if (subtoks.hasMoreTokens()) {
550: String rdir = subtoks.nextToken();
551: String fp = rdir;
552: if (subtoks.hasMoreTokens()) {
553: fp = subtoks.nextToken();
554: } else {
555: rdir = m_DocRoot;
556: }
557: String fn[] = allFiles(rdir, fp);
558: for (int i = 0; i < fn.length; ++i) {
559: checkAdd(map, new PPF_Info(rdir, fn[i], type));
560: }
561: }
562: }
563: }
564:
565: private void addPBFiles(PackagerProps pp, HashMap map, String list,
566: int type) throws ProviderHarnessException {
567: StringTokenizer toks = new StringTokenizer(list, "\r\n");
568: while (toks.hasMoreTokens()) {
569: StringTokenizer subtoks = new StringTokenizer(toks
570: .nextToken(), " \t");
571: if (subtoks.hasMoreTokens()) {
572: String prop = subtoks.nextToken();
573: String fp = prop;
574: if (subtoks.hasMoreTokens()) {
575: fp = subtoks.nextToken();
576: } else {
577: prop = "templateBaseDir";
578: }
579: String rdir = pp.getPBFProperty(prop);
580: String fn[] = allFiles(rdir, fp);
581: for (int i = 0; i < fn.length; ++i) {
582: checkAdd(map, new PPF_Info(prop, rdir, fn[i], type));
583: }
584: }
585: }
586: }
587:
588: // Figure out files from possible directory / filename or ".".
589: // This copies some logic from deployment code - they should really be common.
590:
591: private String[] allFiles(String dir, String fp) {
592: boolean filter = true;
593:
594: if (fp.endsWith("/*") || fp.endsWith("\\*")) {
595: filter = false;
596: fp = fp.substring(0, fp.length() - 2);
597: if (fp.equals("")) {
598: fp = ".";
599: }
600: }
601:
602: File f = null;
603: if (fp.equals(".")) {
604: f = new File(dir);
605: fp = "";
606: } else {
607: f = new File(dir, fp);
608:
609: // If not a directory, just return the single file.
610:
611: if (!f.isDirectory()) {
612: String onefile[] = new String[1];
613: onefile[0] = fp;
614: return onefile;
615: }
616: }
617:
618: // At this point, f should be a directory, and filter indicates
619: // whether we want all files, or just those with the channel name
620: // in their components somewhere.
621:
622: Vector dlist = new Vector();
623: if (!filter || fp.equals(m_ChannelName)) {
624: dlist.add(fp);
625: }
626: addSubDirs(dlist, f, fp, filter);
627:
628: Vector flist = new Vector();
629: for (int i = 0; i < dlist.size(); ++i) {
630: String p = (String) dlist.elementAt(i);
631: File fd = p.equals("") ? new File(dir) : new File(dir, p);
632: File children[] = fd.listFiles();
633: for (int j = 0; j < children.length; ++j) {
634: if (children[j].isDirectory()) {
635: continue;
636: }
637: flist.add(p.equals("") ? children[j].getName() : p
638: + "/" + children[j].getName());
639: }
640: }
641:
642: return (String[]) flist.toArray(new String[flist.size()]);
643: }
644:
645: private void addSubDirs(Vector dlist, File f, String path,
646: boolean filter) {
647: File children[] = f.listFiles();
648: if (children == null) {
649: return;
650: }
651:
652: for (int i = 0; i < children.length; ++i) {
653: File child = children[i];
654: if (child.isDirectory()) {
655: String nm = child.getName();
656: String nmplus = path.equals("") ? nm : path + "/" + nm;
657: if (!filter || nm.equals(m_ChannelName)) {
658: dlist.add(nmplus);
659: addSubDirs(dlist, child, nmplus, false);
660: continue;
661: }
662: addSubDirs(dlist, child, nmplus, filter);
663: }
664: }
665: }
666:
667: // Check to see if a file is really new, or entered with another operation
668: // already.
669:
670: private void checkAdd(HashMap map, PPF_Info inf) {
671: String key = inf.getKey();
672: PPF_Info other = (PPF_Info) map.get(key);
673:
674: if (other != null) {
675: other.addType(inf);
676: return;
677: }
678:
679: map.put(key, inf);
680: }
681:
682: private void refreshSelfInSession() {
683: m_IgnoreClear = true;
684: m_Request.getSession().setAttribute(SESSION_KEY, this );
685: m_IgnoreClear = false;
686: }
687:
688: private static String defaultDocRoot() {
689:
690: String cdir = System.getProperty("ps.docroot");
691: if (cdir != null)
692: return cdir;
693:
694: return DEF_DOCROOT;
695: }
696:
697: private static final String DEF_DOCROOT = "/";
698: private static final String SESSION_KEY = "desktop.Packager";
699:
700: private String m_ConfigDir;
701: private String m_CompFile;
702: private String m_DocRoot;
703: private String m_ParFile;
704: private String m_ProviderImpClass;
705: private String m_ChannelName;
706: private String m_ProviderName;
707: private String m_ProviderClasses;
708: private String m_ProviderPBFiles;
709: private String m_ProviderStaticFiles;
710: private String m_ChannelClasses;
711: private String m_ChannelPBFiles;
712: private String m_ChannelStaticFiles;
713: private boolean m_ProviderActive;
714: private boolean m_ChannelActive;
715: private boolean m_HaveProvider;
716: private boolean m_HaveChannel;
717:
718: private transient HttpServletRequest m_Request = null;
719: private transient HttpServletResponse m_Response = null;
720: private transient PageContext m_PageContext = null;
721: private transient String m_Message = null;
722: private transient String m_ErrorMessage = null;
723: private transient String m_ClassBase = null;
724:
725: private static boolean m_IgnoreClear = false;
726:
727: // Internal class used to construct ProviderPackagFiles incrementally from
728: // our argument strings. Returns a key identifying the file, but not the
729: // type setting.
730:
731: class PPF_Info {
732: PPF_Info(String classname, int type) {
733: m_OpType = type;
734: m_FileType = ParManifest.CLASSFILE;
735: m_ClassName = classname;
736: m_PropName = "";
737: m_Dir = "";
738: m_RelPath = "";
739: }
740:
741: PPF_Info(String property, String propdir, String relpath,
742: int type) {
743: m_OpType = type;
744: m_FileType = ParManifest.PBFILE;
745: m_ClassName = "";
746: m_PropName = property;
747: m_Dir = canon(propdir);
748: m_RelPath = canon(m_Dir, relpath);
749: }
750:
751: PPF_Info(String dir, String path, int type) {
752: m_OpType = type;
753: m_FileType = ParManifest.STATFILE;
754: m_ClassName = "";
755: m_PropName = "";
756: m_Dir = canon(dir);
757: m_RelPath = canon(m_Dir, path);
758: }
759:
760: void addType(PPF_Info other) {
761: m_OpType |= other.m_OpType;
762: }
763:
764: String getKey() {
765: return "(" + m_FileType + ")" + m_ClassName + "+"
766: + m_PropName + "+" + m_Dir + File.pathSeparator
767: + m_RelPath;
768: }
769:
770: ProviderPackageFile getPPF() {
771: switch (m_FileType) {
772: case ParManifest.STATFILE:
773: return new StaticPPF(m_Dir, m_RelPath, m_OpType);
774: case ParManifest.PBFILE:
775: return new PropLocPPF(m_PropName, m_Dir, m_RelPath,
776: m_OpType);
777: default:
778: return new ClassLoadPPF(m_ClassName, m_OpType);
779: }
780: }
781:
782: // If we cannot canonicalize paths, take their present form.
783:
784: private String canon(String path) {
785: File f = new File(path);
786: try {
787: return reverseBS(f.getCanonicalPath());
788: } catch (Exception ex) {
789: return reverseBS(path);
790: }
791: }
792:
793: // dir has already been canonicalized.
794:
795: private String canon(String dir, String rel) {
796: File f = new File(dir, rel);
797: try {
798: String p = f.getCanonicalPath();
799: // somewhat abusive - we "know" file separators are 1 character
800: return reverseBS(p.substring(dir.length() + 1));
801: } catch (Exception ex) {
802: return reverseBS(rel);
803: }
804: }
805:
806: private String reverseBS(String str) {
807:
808: String pfx;
809: if (str.startsWith("\\")) {
810: pfx = "/";
811: str = str.substring(1);
812: } else {
813: pfx = "";
814: }
815:
816: StringTokenizer toks = new StringTokenizer(str, "\\");
817: StringBuffer buf = new StringBuffer();
818: while (toks.hasMoreTokens()) {
819: buf.append(pfx);
820: buf.append(toks.nextToken());
821: pfx = "/";
822: }
823:
824: return buf.toString();
825: }
826:
827: int m_OpType;
828: int m_FileType;
829: String m_ClassName;
830: String m_Dir;
831: String m_RelPath;
832: String m_PropName;
833: }
834:
835: class ClassLoadPPF extends ClassPPF {
836:
837: ClassLoadPPF(String classname, int types) {
838: super (classname, types);
839: m_ClassName = classname;
840: m_Types = types;
841: }
842:
843: public InputStream getStream() throws ParFileException {
844: StringTokenizer toks = new StringTokenizer(m_ClassName, ".");
845: String pfx = "";
846: StringBuffer cfname = new StringBuffer();
847: while (toks.hasMoreTokens()) {
848: cfname.append(pfx);
849: pfx = "/";
850: cfname.append(toks.nextToken());
851: }
852: cfname.append(".class");
853: InputStream strm = ClassLoader
854: .getSystemResourceAsStream(cfname.toString());
855: if (strm == null) {
856: File f = new File(m_ClassBase, cfname.toString());
857: try {
858: strm = new FileInputStream(f);
859: } catch (Exception ex) {
860: throw new ParFileException(
861: "Cannot open class file - "
862: + cfname.toString());
863: }
864: }
865: return strm;
866: }
867:
868: public boolean classExists() {
869: return true;
870: }
871:
872: int m_Types;
873: String m_ClassName;
874: }
875: }
|