001: /**
002: * $Id: CreatePAR.java,v 1.21 2007/01/26 03:48:20 portalbld Exp $
003: * Copyright 2004 Sun Microsystems, Inc. All
004: * rights reserved. Use of this product is subject
005: * to license terms. Federal Acquisitions:
006: * Commercial Software -- Government Users
007: * Subject to Standard License Terms and
008: * Conditions.
009: *
010: * Sun, Sun Microsystems, the Sun logo, and Sun ONE
011: * are trademarks or registered trademarks of Sun Microsystems,
012: * Inc. in the United States and other countries.
013: */package com.sun.portal.desktop.admin.mbeans.tasks;
014:
015: import java.io.InputStream;
016: import java.io.InputStreamReader;
017: import java.io.FileInputStream;
018: import java.io.FileOutputStream;
019: import java.io.File;
020: import java.io.FileNotFoundException;
021: import java.io.IOException;
022: import java.io.ByteArrayInputStream;
023:
024: import java.util.Iterator;
025: import java.util.Vector;
026: import java.util.Map;
027: import java.util.HashMap;
028: import java.util.Set;
029: import java.util.LinkedHashSet;
030: import java.util.HashSet;
031: import java.util.Properties;
032: import java.util.StringTokenizer;
033: import java.util.logging.Level;
034: import java.util.logging.Logger;
035: import java.util.Locale;
036: import java.util.regex.Pattern;
037:
038: import java.net.URLEncoder;
039:
040: import org.w3c.dom.Document;
041: import org.w3c.dom.Element;
042:
043: import org.xml.sax.InputSource;
044: import org.xml.sax.SAXException;
045: import org.xml.sax.SAXParseException;
046:
047: import javax.xml.parsers.DocumentBuilder;
048: import javax.xml.parsers.DocumentBuilderFactory;
049: import javax.xml.parsers.ParserConfigurationException;
050:
051: import com.sun.portal.log.common.PortalLogger;
052: import com.sun.portal.log.common.PortalLogManager;
053:
054: import com.sun.portal.admin.common.PSConfigConstants;
055: import com.sun.portal.admin.common.BackupVersion;
056: import com.sun.portal.util.DTDResolver;
057:
058: import com.sun.portal.community.mc.CMCRolePrincipal;
059:
060: import com.sun.portal.desktop.dp.xml.XMLDPFactory;
061: import com.sun.portal.desktop.dp.xml.XMLDPRoot;
062: import com.sun.portal.desktop.dp.DPError;
063: import com.sun.portal.desktop.context.DPContext;
064: import com.sun.portal.desktop.context.DSAMEAdminDPContext;
065:
066: import com.sun.portal.desktop.deployment.DPBasedPPCtx;
067: import com.sun.portal.desktop.deployment.ParFileBuilder;
068: import com.sun.portal.desktop.deployment.ParFileException;
069: import com.sun.portal.desktop.deployment.Par;
070: import com.sun.portal.desktop.deployment.ParManifest;
071: import com.sun.portal.desktop.deployment.ProviderPackageContext;
072: import com.sun.portal.desktop.deployment.ExtractOp;
073:
074: import com.sun.portal.util.Platform;
075:
076: /**
077: * This class provide functionality to create a PAR file from an existing
078: * directory structure.
079: */
080: public class CreatePAR {
081:
082: public static final String DP_MAPPING = "DPMapping.properties";
083: public static final String TEMPLATE_BASE_DIR_PROP = "templateBaseDir";
084:
085: // Community templates static strings
086: public static final String COMMUNITY_TEMPLATE_BASE_DIR_PROP = "communityTemplateBaseDir";
087:
088: public static final String UTF8 = "UTF-8";
089: public static final String GLOBAL_KEY = "global";
090: public static final String DESKTOP = "desktop";
091: public static final String MERGED_ORDER = "mergedOrder";
092: public static final String LOCALIZED_PATH = "_localized";
093:
094: // File separator.
095: public static final String FS = Platform.fs;
096:
097: // Logger
098: static private Logger m_Logger = null;
099:
100: private String m_DPNode = null;
101: private Properties m_DPProps = null;
102: private File m_DPRootDir = null;
103:
104: /**
105: * Constructor
106: */
107: public CreatePAR() {
108: PortalLogManager manager = new PortalLogManager();
109: manager.init("debug.com.sun.portal");
110:
111: m_Logger = PortalLogger.getLogger(CreatePAR.class);
112: }
113:
114: /**
115: * Creates a par file from a directory structure that conforms to the
116: * PAR file format.
117: *
118: * @param parFileName The absolute file name for the output PAR file
119: * @exception Exception If error occurs when creating the file
120: */
121: public void parFromDir(String path, String parFileName)
122: throws Exception, Throwable {
123:
124: if (path.endsWith(FS)) {
125: path = path.substring(0, (path.length() - 1));
126: }
127:
128: File f = new File(parFileName);
129: if (f.exists()) {
130: m_Logger.log(Level.WARNING, "PSDT_CSPDAMT0098");
131: f.delete();
132: }
133:
134: try {
135:
136: ProviderPackageContext ppctx = new DPBasedPPCtx(null, null);
137: Map parDocs = new HashMap();
138: Map dpMappings = new HashMap();
139: Properties dtProps = new Properties();
140: // We need to set a property in the that lets PAR API's know where
141: // the desktop JSPs are located in the directory layout.
142: String templateBaseDirPath = path + FS
143: + ParManifest.DEF_PBFILES_STR + FS
144: + TEMPLATE_BASE_DIR_PROP;
145: dtProps.setProperty(TEMPLATE_BASE_DIR_PROP,
146: templateBaseDirPath);
147: String communityTemplateBaseDirPath = path + FS
148: + ParManifest.DEF_PBFILES_STR + FS
149: + COMMUNITY_TEMPLATE_BASE_DIR_PROP;
150: dtProps.setProperty(COMMUNITY_TEMPLATE_BASE_DIR_PROP,
151: communityTemplateBaseDirPath);
152: ppctx.setDTProps(dtProps);
153: //ppctx.setLogger(m_Logger);
154:
155: // The docs map contains all the dp documents, in the dp directory
156: // it uses dn as the key and the value is dp doc stored in
157: // that dn.
158: boolean dpExists = setupDPAndProp(path);
159: Map docs = null;
160: if (dpExists) {
161: docs = getDPDocObjectMap(path, dpMappings);
162: if (m_DPNode == null) {
163: m_DPNode = "";
164: }
165: }
166:
167: Set keys = null;
168:
169: if (docs != null && !docs.isEmpty()) {
170: keys = docs.keySet();
171:
172: for (Iterator i = keys.iterator(); i.hasNext();) {
173: String key = (String) i.next();
174: // Create par entry, and add it in the parDocs map
175: Element e = (Element) docs.get(key);
176: Document parEntry = Par.makeParEntry(key, null, e);
177: if (parEntry != null) {
178: Object tokens[] = { key };
179: m_Logger.log(Level.INFO, "PSDT_CSPDAMT0099",
180: tokens);
181:
182: if (key.equals(GLOBAL_KEY)) {
183: parDocs.put(GLOBAL_KEY, parEntry);
184: } else {
185: parDocs.put(URLEncoder.encode(key, UTF8),
186: parEntry);
187: }
188: }
189: }
190: }
191:
192: // The properties map contains all attributes properties,
193: // it uses dn as the key. The properties map contains one Properties
194: // object per dn, and the Properties object contains the desktop
195: // service attribute name and value pairs.
196: Map properties = dpExists ? getPropertyObjectMap(path,
197: dpMappings) : null;
198: ExtractOp op = dpMappings.isEmpty() ? null : ExtractOp
199: .makeOpWithDPMapping(m_DPNode, dpMappings);
200:
201: // add provider/channel related template files
202: // using DPBasedPPCtx.addDirectory() method to generate list
203: // of files which is under the templateBaseDir. For global
204: // export, this will archive ALL files under the
205: // templateBaseDir. For dn based export, this will archive
206: // the files base on the corresponding desktop type.
207: Vector files = new Vector();
208:
209: m_Logger.log(Level.INFO, "PSDT_CSPDAMT0100");
210: ppctx.addDirectory(TEMPLATE_BASE_DIR_PROP, null, true,
211: false, null, ExtractOp.TYPE_OTHER, null, files);
212:
213: m_Logger.log(Level.INFO, "PSDT_CSPDAMT0116");
214:
215: // Special treatment for community dp templates
216: mergeCommunityDps(communityTemplateBaseDirPath);
217: ppctx.addDirectory(COMMUNITY_TEMPLATE_BASE_DIR_PROP, null,
218: true, true, null, ExtractOp.TYPE_OTHER,
219: LOCALIZED_PATH, files);
220:
221: // add files from web-src
222: String webSrcPath = path + FS + ParManifest.DEF_STATIC_STR
223: + FS + PSConfigConstants.WEB_SRC;
224:
225: System.setProperty(ProviderPackageContext.STATICDIR,
226: webSrcPath);
227:
228: if (m_Logger.isLoggable(Level.INFO)) {
229: Object tokens[] = { webSrcPath };
230: m_Logger.log(Level.INFO, "PSDT_CSPDAMT0101", tokens);
231:
232: }
233:
234: ppctx.addDirectory(null, null, true, true, null,
235: ExtractOp.TYPE_OTHER, null, files);
236:
237: // add portlet war files
238: String warDir = path + FS + ProviderPackageContext.WAR;
239: System.setProperty(ProviderPackageContext.PSWARDIR, warDir);
240:
241: if (m_Logger.isLoggable(Level.INFO)) {
242: Object tokens[] = { warDir };
243: m_Logger.log(Level.INFO, "PSDT_CSPDAMT0102", tokens);
244: }
245:
246: ppctx.addDirectory(ProviderPackageContext.PSWARDIR, null,
247: false, true, null, ExtractOp.TYPE_OTHER, null,
248: files);
249:
250: // build a backupVersion number, which is:
251: // <domain name>;<portalName>;<backup type>;<backup version>
252: String backupVersion = BackupVersion.generateBackupVersion(
253: "---", "---", DESKTOP);
254:
255: if (m_Logger.isLoggable(Level.INFO)) {
256: Object tokens[] = { parFileName };
257: m_Logger.log(Level.INFO, "PSDT_CSPDAMT0103", tokens);
258: }
259:
260: ParFileBuilder pfb = new ParFileBuilder(true, m_Logger,
261: backupVersion);
262:
263: // add the dp entry in par file, then make the par file
264: pfb.addDPEntry("global", parDocs, files, properties, op);
265: pfb.makeParFile(parFileName);
266:
267: } catch (Exception e) {
268: m_Logger.log(Level.SEVERE, "PSDT_CSPDAMT0104", e);
269: throw e;
270: } catch (Throwable t) {
271: m_Logger.log(Level.SEVERE, "PSDT_CSPDAMT0104", t);
272: throw t;
273: }
274:
275: m_Logger.log(Level.INFO, "PSDT_CSPDAMT0105");
276: }
277:
278: /*
279: * Convenient method to get a property from a properties file.
280: */
281: private Properties getProp(String name) throws DesktopDataException {
282:
283: Properties prop = new Properties();
284: try {
285: InputStream is = new FileInputStream(name);
286: prop.load(is);
287: is.close();
288: } catch (FileNotFoundException fne) {
289: m_Logger.log(Level.SEVERE, "PSDT_CSPDAMT0106", fne);
290: throw new DesktopDataException(fne.getMessage(), fne);
291: } catch (Exception se) {
292: m_Logger.log(Level.SEVERE, "PSDT_CSPDAMT0073", se);
293: throw new DesktopDataException(se.getMessage(), se);
294: }
295:
296: return prop;
297: }
298:
299: private boolean setupDPAndProp(String path) {
300:
301: String dpDir = path + FS + ParManifest.DEF_DP_STR;
302: String mapFileName = dpDir + FS + DP_MAPPING;
303:
304: try {
305:
306: if (m_DPRootDir == null) {
307: m_DPRootDir = new File(dpDir);
308: }
309:
310: if (!m_DPRootDir.exists()) {
311: Object tokens[] = { dpDir };
312: m_Logger.log(Level.WARNING, "PSDT_CSPDAMT0107", tokens);
313: m_Logger.log(Level.WARNING, "PSDT_CSPDAMT0108");
314: return false;
315: }
316:
317: if (m_DPProps == null) {
318: m_DPProps = getProp(mapFileName);
319: }
320: } catch (DesktopDataException de) {
321: m_Logger.log(Level.WARNING, "PSDT_CSPDAMT0072", de);
322: m_Logger.log(Level.WARNING, "PSDT_CSPDAMT0109");
323: return false;
324: }
325:
326: //set dpnode if found
327: m_DPNode = (String) m_DPProps.get(ExtractOp.ARG_DPNODE);
328:
329: return true;
330:
331: }
332:
333: private void validateMappingFile(String ext)
334: throws DesktopDataException {
335:
336: Set keys = m_DPProps.keySet();
337: File children[] = m_DPRootDir.listFiles();
338:
339: //check if all dp are defined in the mapping file
340: for (int i = 0; i < children.length; i++) {
341: String name = children[i].getName();
342: boolean found = false;
343: for (Iterator it = keys.iterator(); it.hasNext();) {
344: String key = (String) it.next();
345: if (key.equals(ExtractOp.ARG_DPNODE)) {
346: continue;
347: }
348:
349: if (name.endsWith(ext) && name.startsWith(key)) {
350: found = true;
351: break;
352: }
353: }
354:
355: // Escape DPMapping
356: if (!name.equals(DP_MAPPING) && name.endsWith(ext)
357: && found == false) {
358: name = name.substring(0, name.indexOf(ext));
359: throw new DesktopDataException(
360: "CreatePAR.validateMappingFile(), entry is not found in the mapping file: "
361: + name);
362: }
363: }
364: }
365:
366: private Map getDPDocObjectMap(String path, Map dpMappings)
367: throws DesktopDataException {
368: Map docs = new HashMap();
369: String dpDir = path + FS + ParManifest.DEF_DP_STR;
370:
371: validateMappingFile(".xml");
372:
373: Set keys = m_DPProps.keySet();
374: File children[] = m_DPRootDir.listFiles();
375:
376: for (Iterator it = keys.iterator(); it.hasNext();) {
377: Set dps = new HashSet();
378: String subName = null;
379: String key = (String) it.next();
380: String val = (String) m_DPProps.getProperty(key);
381: if (m_Logger.isLoggable(Level.FINER)) {
382: Object tokens[] = { key };
383: m_Logger.log(Level.FINER, "PSDT_CSPDAMT0110", tokens);
384: }
385:
386: if (key.equals(ExtractOp.ARG_DPNODE)) {
387: continue;
388: }
389:
390: for (int i = 0; i < children.length; i++) {
391: File child = children[i];
392: String name = child.getName();
393:
394: if (name.endsWith(".xml")) {
395: //name = name.substring(0, name.indexOf(".xml"));
396:
397: // find if dp xml match to any key from the mapping
398: // file
399: if (name.startsWith(key)) {
400: dps.add(name);
401: if (m_Logger.isLoggable(Level.FINER)) {
402: Object tokens[] = { name };
403: m_Logger.log(Level.FINER,
404: "PSDT_CSPDAMT0111", tokens);
405: }
406: }
407: }
408: }
409:
410: if (dps.size() == 1) {
411: Object array[] = new Object[1];
412: dps.toArray(array);
413: Document doc = getDocument(dpDir + FS + array[0]);
414: docs.put(key, doc.getDocumentElement());
415: dpMappings.put(key, val);
416: } else if (dps.size() > 0) {
417: String mergedOrder = (String) m_DPProps
418: .get(MERGED_ORDER + "-" + key);
419: m_Logger.log(Level.FINER, "PSDT_CSPDAMT0115",
420: mergedOrder);
421: StringTokenizer st = (mergedOrder == null) ? null
422: : new StringTokenizer(mergedOrder, ",");
423: Set ls = new LinkedHashSet();
424:
425: if (st != null) {
426: while (st.hasMoreTokens()) {
427: String token = (String) st.nextToken().trim();
428: if (dps.contains(token)) {
429: ls.add(token);
430: dps.remove(token);
431: }
432: }
433: if (!dps.isEmpty()) {
434: ls.addAll(dps);
435: }
436: } else {
437: ls.addAll(dps);
438: }
439:
440: //combine dp with same name into one dp
441: XMLDPRoot dpr = combineDP(null, dpDir, ls);
442:
443: if (dpr != null) {
444: docs.put(key, dpr.getElement());
445: dpMappings.put(key, val);
446: }
447: }
448: }
449: return docs;
450: }
451:
452: private Map getPropertyObjectMap(String path, Map dpMappings)
453: throws DesktopDataException {
454: Map propMap = new HashMap();
455: String dpDir = path + FS + ParManifest.DEF_DP_STR;
456:
457: validateMappingFile(".properties");
458:
459: Set keys = m_DPProps.keySet();
460: Set mappingKeys = dpMappings.keySet();
461: File children[] = m_DPRootDir.listFiles();
462:
463: for (Iterator it = keys.iterator(); it.hasNext();) {
464: String key = (String) it.next();
465: if (m_Logger.isLoggable(Level.FINER)) {
466: Object tokens[] = { key };
467: m_Logger.log(Level.FINER, "PSDT_CSPDAMT0110", tokens);
468: }
469:
470: if (key.equals(ExtractOp.ARG_DPNODE)) {
471: continue;
472: }
473:
474: for (int i = 0; i < children.length; i++) {
475: File child = children[i];
476: String name = child.getName();
477: Properties props = null;
478:
479: if (name.endsWith(".properties")) {
480: //don't store DPMapping
481: if (name.equals(DP_MAPPING)) {
482: continue;
483: }
484: if (name.startsWith(key)) {
485: if (!mappingKeys.contains(key)) {
486: dpMappings.put(key, (String) m_DPProps
487: .get(key));
488: }
489: props = getProp(dpDir + FS + key
490: + ".properties");
491: propMap.put(key, props);
492: if (m_Logger.isLoggable(Level.FINER)) {
493: Object tokens[] = { dpDir + FS + name };
494: m_Logger.log(Level.FINER,
495: "PSDT_CSPDAMT0112", tokens);
496: }
497:
498: break;
499: }
500: }
501: }
502: }
503:
504: return propMap;
505: }
506:
507: private XMLDPRoot combineDP(XMLDPRoot rootDpr, String rootPath,
508: Set dps) throws DesktopDataException {
509: Iterator i = dps.iterator();
510: String next = null;
511: XMLDPRoot dpr = null;
512: XMLDPFactory dpf = XMLDPFactory.getInstance();
513: DPContext dc = (DPContext) new DSAMEAdminDPContext();
514: Document doc = null;
515: String dp = null;
516:
517: try {
518: if (rootDpr == null) {
519: //get the first dp
520: while (dp == null) {
521: if (i.hasNext()) {
522: String first = (String) i.next();
523: if (m_Logger.isLoggable(Level.FINER)) {
524: Object tokens[] = { rootPath + FS + first };
525: m_Logger.log(Level.FINEST,
526: "PSDT_CSPDAMT0113", tokens);
527: }
528: dp = DPHelper
529: .generateDPDocument(getDocument(rootPath
530: + FS + first));
531: if (dp == null) {
532: if (m_Logger.isLoggable(Level.WARNING)) {
533: Object tokens[] = { first };
534: m_Logger.log(Level.WARNING,
535: "PSDT_CSPDAMT0114", tokens);
536: }
537: } else {
538: rootDpr = (XMLDPRoot) dpf
539: .createRoot(dc, dp);
540: break;
541: }
542: }
543: }
544: }
545:
546: while (i.hasNext()) {
547: next = (String) i.next();
548: if (m_Logger.isLoggable(Level.FINER)) {
549: Object tokens[] = { rootPath + FS + next };
550: m_Logger.log(Level.FINEST, "PSDT_CSPDAMT0113",
551: tokens);
552: }
553: dp = DPHelper.generateDPDocument(getDocument(rootPath
554: + FS + next));
555: if (dp == null) {
556: if (m_Logger.isLoggable(Level.WARNING)) {
557: Object tokens[] = { next };
558: m_Logger.log(Level.WARNING, "PSDT_CSPDAMT0114",
559: tokens);
560: }
561: } else {
562: dpr = (XMLDPRoot) dpf.createRoot(dc, dp);
563: try {
564: DPAUtil.combineRoots(rootDpr, dpr);
565: } catch (DPError de) {
566: // hack around exception thrown from XMLDPRoot
567: // when priority is not an integer
568: String msg = de.getMessage();
569: if (msg.indexOf("priority") == -1) {
570: throw de;
571: }
572: }
573: }
574: }
575: } catch (DPAException de) {
576: throw new DesktopDataException("CreatePAR.combineDP()", de);
577: }
578:
579: // Set dirty to false before writing out. Not doing this will cause
580: // "dirty=true" attribute to be added which will cause validation error.
581: if (rootDpr.isDirty()) {
582: rootDpr.setDirty(false);
583: }
584:
585: return rootDpr;
586: }
587:
588: private XMLDPRoot combineCommunityDP(String rootPath, String name,
589: Set dps) throws DesktopDataException {
590: String dp = null;
591: XMLDPRoot rootDpr = null;
592: XMLDPFactory dpf = XMLDPFactory.getInstance();
593: DPContext dc = (DPContext) new DSAMEAdminDPContext();
594:
595: dp = DPHelper.generateDPDocument(getDocument(rootPath + FS
596: + name));
597: if (dp == null) {
598: throw new DesktopDataException(
599: "CreatePAR.combineCommunityDP(): Can not get dp from: "
600: + name);
601: } else {
602: rootDpr = (XMLDPRoot) dpf.createRoot(dc, dp);
603: }
604: return combineDP(rootDpr, rootPath + FS + LOCALIZED_PATH, dps);
605: }
606:
607: private Document getDocument(String xmlFilePath)
608: throws DesktopDataException {
609:
610: Document d = null;
611: try {
612: FileInputStream fi = new FileInputStream(new File(
613: xmlFilePath));
614: byte[] bytes = new byte[fi.available()];
615: fi.read(bytes);
616: fi.close();
617:
618: ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
619:
620: InputSource is = new InputSource(bi);
621: DocumentBuilderFactory dbf = DocumentBuilderFactory
622: .newInstance();
623: dbf.setValidating(false);
624:
625: DocumentBuilder db = dbf.newDocumentBuilder();
626: DTDResolver dtdReso = new DTDResolver();
627: db.setEntityResolver(dtdReso);
628: db.setErrorHandler(dtdReso);
629: d = db.parse(is);
630:
631: } catch (SAXParseException spe) {
632: throw new DesktopDataException(
633: "createPAR.getDocument(), xml parsing error, see dp document "
634: + xmlFilePath + ": line="
635: + spe.getLineNumber() + ". ", spe);
636: } catch (SAXException se) {
637: throw new DesktopDataException("createPAR.getDocment():",
638: se);
639: } catch (ParserConfigurationException pce) {
640: throw new DesktopDataException("createPAR.getDocment():",
641: pce);
642: } catch (IOException ioe) {
643: throw new DesktopDataException("createPAR.getDocment():",
644: ioe);
645: }
646: return d;
647: }
648:
649: /*
650: * Merge community template dps.
651: *
652: * This is to support the community localized dp templates.
653: */
654: private void mergeCommunityDps(String path)
655: throws DesktopDataException {
656:
657: File parent = null;
658: // Skip the step if path does not exists
659: if (path != null) {
660: parent = new File(path);
661: }
662:
663: if (parent != null && parent.isDirectory()) {
664: File subs[] = parent.listFiles();
665: for (int i = 0; i < subs.length; i++) {
666: File sub = subs[i];
667: if (!sub.isDirectory()) {
668: continue;
669: }
670:
671: for (Iterator it = CMCRolePrincipal.ALL_ROLES
672: .iterator(); it.hasNext();) {
673: // get role name and find dps for this role, and
674: // combine the dps
675:
676: CMCRolePrincipal r = (CMCRolePrincipal) it.next();
677: String name = (String) r.toString();
678: Set dps = new HashSet();
679: File localizedDir = new File(sub.getPath(),
680: LOCALIZED_PATH);
681:
682: if (localizedDir.exists()) {
683: File files[] = localizedDir.listFiles();
684: if (files == null) {
685: continue;
686: }
687:
688: for (int k = 0; k < files.length; k++) {
689: File file = files[k];
690:
691: if (file.getName().endsWith(".xml")) {
692: if (file.getName().startsWith(name)
693: && checkLocale(file.getName())) {
694: m_Logger.log(Level.INFO,
695: "add file:"
696: + file.getName());
697: dps.add(file.getName());
698: }
699: }
700: }
701:
702: XMLDPRoot dpr = null;
703:
704: if (dps.size() > 1) {
705: dpr = combineCommunityDP(sub.getPath(),
706: name + ".xml", dps);
707: if (dpr != null) {
708: if (dpr.isDirty()) {
709: dpr.setDirty(false);
710: }
711: String dp = dpr.toString();
712: createDPFile(sub.getPath(), name, dp);
713: }
714: }
715: }
716: }
717: }
718: }
719: }
720:
721: private boolean checkLocale(String fn) {
722: String n = fn.substring(0, fn.indexOf(".xml"));
723: StringTokenizer st = new StringTokenizer(n, "_");
724: String[] countries = Locale.getISOCountries();
725: String[] languages = Locale.getISOLanguages();
726: StringBuffer lang = new StringBuffer("(");
727: StringBuffer coun = new StringBuffer("(");
728:
729: if (st.countTokens() == 1) {
730: return true;
731: }
732:
733: for (int i = 0; i < languages.length; i++) {
734: lang.append(languages[i]).append("|");
735: }
736: lang.append(")");
737: for (int i = 0; i < countries.length; i++) {
738: coun.append(countries[i]).append("|");
739: }
740: coun.append(")");
741:
742: String l = null;
743: String c = null;
744: st.nextToken();
745:
746: if (st.hasMoreTokens()) {
747: l = st.nextToken();
748: }
749:
750: if (Pattern.matches(lang.toString(), l)) {
751: if (st.hasMoreTokens()) {
752: c = st.nextToken();
753: }
754:
755: if (c == null) {
756: return true;
757: }
758:
759: if (Pattern.matches(coun.toString(), c)) {
760: return true;
761: }
762:
763: }
764:
765: return false;
766: }
767:
768: private void createDPFile(String path, String name, String dp)
769: throws DesktopDataException {
770: byte[] bytes = null;
771:
772: try {
773: bytes = dp.getBytes(UTF8);
774: } catch (java.io.UnsupportedEncodingException ue) {
775: //This may never happen because utf-8 is always supported!
776: bytes = dp.getBytes();
777: }
778:
779: try {
780: File file = new File(path, name + ".xml");
781: FileOutputStream fo = new FileOutputStream(file);
782: fo.write(bytes);
783: fo.close();
784: } catch (IOException ie) {
785: throw new DesktopDataException(
786: "createPAR.createDPFile(): ", ie);
787: }
788: }
789:
790: /**
791: * @param args the command line arguments
792: */
793: public static void main(String args[]) {
794:
795: if (args != null && args.length == 2) {
796:
797: try {
798: CreatePAR cp = new CreatePAR();
799: cp.parFromDir(args[0], args[1]);
800: } catch (Exception e) {
801: e.printStackTrace();
802: System.exit(-1);
803: } catch (Throwable t) {
804: t.printStackTrace();
805: System.exit(-1);
806: }
807:
808: } else {
809: // TODO add more usage help
810: System.out.println("Error: Insufficient arguments");
811: System.exit(-1);
812: }
813: System.out.println("Create par completed!");
814: System.exit(0);
815: }
816:
817: }
|