001: /*
002: * Copyright 2001 Sun Microsystems, Inc. All rights reserved.
003: * PROPRIETARY/CONFIDENTIAL. Use of this product is subject to license terms.
004: */
005: package com.sun.portal.subscriptions.profiler.cli;
006:
007: import com.sun.portal.admin.common.util.AdminUtil;
008: import java.util.Map;
009: import java.util.TreeMap;
010: import java.util.Set;
011: import java.util.HashSet;
012: import java.util.List;
013: import java.util.HashMap;
014: import java.util.ArrayList;
015: import java.util.ResourceBundle;
016: import java.util.PropertyResourceBundle;
017: import java.util.Locale;
018: import java.util.Iterator;
019: import java.util.Properties;
020: import java.util.StringTokenizer;
021: import java.text.MessageFormat;
022:
023: import java.io.BufferedReader;
024: import java.io.StringReader;
025: import java.io.InputStreamReader;
026: import java.io.FileInputStream;
027: import java.io.ByteArrayInputStream;
028: import java.io.InputStream;
029: import java.io.IOException;
030: import java.io.BufferedInputStream;
031:
032: import com.iplanet.sso.SSOToken;
033: import com.iplanet.sso.SSOException;
034: import com.iplanet.sso.SSOTokenManager;
035:
036: import com.iplanet.am.sdk.AMObject;
037: import com.iplanet.am.sdk.AMConstants;
038: import com.iplanet.am.sdk.AMUser;
039: import com.iplanet.am.sdk.AMException;
040: import com.iplanet.am.sdk.AMStoreConnection;
041: import com.iplanet.am.sdk.AMOrganization;
042: import com.iplanet.am.sdk.AMRole;
043: import com.iplanet.am.sdk.AMTemplate;
044: import com.iplanet.am.sdk.AMPeopleContainer;
045: import com.iplanet.am.sdk.AMSearchControl;
046: import com.iplanet.am.sdk.AMSearchResults;
047: import com.iplanet.am.util.AdminUtils;
048: import com.iplanet.am.util.SystemProperties;
049:
050: import com.sun.identity.authentication.internal.AuthPrincipal;
051: import com.sun.identity.authentication.spi.AuthLoginException;
052:
053: import com.sun.portal.search.soif.SOIFInputStream;
054: import com.sun.portal.search.soif.SOIF;
055: import com.sun.portal.subscriptions.providers.Subscription;
056: import com.sun.portal.subscriptions.providers.SearchSubscription;
057: import com.sun.portal.subscriptions.profiler.ProfilerException;
058:
059: import com.sun.portal.desktop.dp.cli.CLIPParser;
060: import com.sun.portal.desktop.dp.cli.CLIPException;
061: import com.sun.portal.admin.common.PSConfigConstants;
062:
063: // profiler related imports
064: import com.sun.portal.subscriptions.profiler.*;
065: import com.sun.portal.log.common.PortalLogger;
066:
067: import java.io.*;
068: import java.util.Properties;
069: import java.util.*;
070: import java.util.logging.Level;
071: import java.util.logging.Logger;
072:
073: /**
074: * Description of the Class
075: *
076: * @author pm95875 @created September 2, 2003
077: */
078: public class ProfilerCmd {
079:
080: // default value for unrequired options
081: /**
082: * Description of the Field
083: *
084: * @since
085: */
086: public final static String OPT_DEFAULT = "*";
087:
088: //default value for the locale option
089: /**
090: * Description of the Field
091: *
092: * @since
093: */
094: public final static String LOCALE_DEFAULT = Locale.getDefault()
095: .toString();
096:
097: // subcommands
098: /**
099: * Description of the Field
100: *
101: * @since
102: */
103: public final static String STOP = "stop";
104: /**
105: * Description of the Field
106: *
107: * @since
108: */
109: public final static String RUN = "run";
110: /**
111: * Description of the Field
112: *
113: * @since
114: */
115: public final static int SUBCMD_STOP = 1;
116: /**
117: * Description of the Field
118: *
119: * @since
120: */
121: public final static int SUBCMD_RUN = 2;
122:
123: // options
124: /**
125: * Description of the Field
126: *
127: * @since
128: */
129: protected final static String HELP = "help";
130: /**
131: * Description of the Field
132: *
133: * @since
134: */
135: protected final static String UID = "uid";
136: /**
137: * Description of the Field
138: *
139: * @since
140: */
141: protected final static String ORGANIZATION = "organization";
142: /**
143: * Description of the Field
144: *
145: * @since
146: */
147: protected final static String PORTAL = "portal";
148: /**
149: * Description of the Field
150: *
151: * @since
152: */
153: protected final static String NAME = "name";
154: /**
155: * Description of the Field
156: *
157: * @since
158: */
159: protected final static String PARENT = "parent";
160: /**
161: * Description of the Field
162: *
163: * @since
164: */
165: protected final static String TYPE = "type";
166:
167: /**
168: * Description of the Field
169: *
170: * @since
171: */
172: protected final static String VERBOSE = "verbose";
173: /**
174: * Description of the Field
175: *
176: * @since
177: */
178: protected final static String VERSION = "version";
179: /**
180: * Description of the Field
181: *
182: * @since
183: */
184: protected final static String LOCALE = "locale";
185: /**
186: * Description of the Field
187: *
188: * @since
189: */
190: protected final static String CONT = "continue";
191: /**
192: * Description of the Field
193: *
194: * @since
195: */
196: protected final static String FILE = "file";
197:
198: // option values
199: /**
200: * Description of the Field
201: *
202: * @since
203: */
204: protected int subcmd = -1;
205: /**
206: * Description of the Field
207: *
208: * @since
209: */
210: protected String uid = null;
211: /**
212: * Description of the Field
213: *
214: * @since
215: */
216: protected String dn = null;
217: /**
218: * Description of the Field
219: *
220: * @since
221: */
222: protected String organization = null;
223: /**
224: * Description of the Field
225: *
226: * @since
227: */
228: protected boolean verbose = false;
229: /**
230: * Description of the Field
231: *
232: * @since
233: */
234: protected boolean version = false;
235: /**
236: * Description of the Field
237: *
238: * @since
239: */
240: protected String name = null;
241: /**
242: * Description of the Field
243: *
244: * @since
245: */
246: protected String parent = null;
247: /**
248: * Description of the Field
249: *
250: * @since
251: */
252: protected String type = null;
253: /**
254: * portalid default value is "Upgraded" for backward compatibility with 6.3
255: * in 7.0, the environment variable PS_DEFAUTL_PORTAL is set by psEnv.sh
256: * that is considered as the value to use.
257: * @since
258: */
259: protected String portalId = null;
260: /**
261: * Description of the Field
262: *
263: * @since
264: */
265: protected boolean cont = false;
266:
267: // profiler specific attributes
268: Properties profilerProps = null;
269: Properties notifierProps = null;
270: AMStoreConnection sConnection = null;
271: SSOToken ssoToken = null;
272: Set subsUserSet = null;;
273: String adminUID = null;
274: String adminPWD = null;
275: String runtimePropPath = null;
276:
277: public static final String RESOURCE_BASE = "profiler";
278: public static ResourceBundle rb = PropertyResourceBundle.getBundle(
279: RESOURCE_BASE, Locale.getDefault());
280: private static Logger logger = PortalLogger
281: .getLogger(ProfilerCmd.class);
282:
283: public ProfilerCmd() {
284: runtimePropPath = System.getProperty("PS_DATA_DIR")
285: + File.separator + "portals" + File.separator
286: + portalId + File.separator + "config" + File.separator
287: + PSConfigConstants.PS_PROFILER_CONFIG_FILE;
288: }
289:
290: public ProfilerCmd(String runtimePropPath, String portalId,
291: String orgDN, String users, String adminUID,
292: String adminPWD, int cmd) {
293: this .runtimePropPath = runtimePropPath;
294: this .organization = orgDN;
295: this .portalId = portalId;
296: this .uid = users;
297: this .adminUID = adminUID;
298: this .adminPWD = adminPWD;
299: this .subcmd = cmd;
300: }
301:
302: /**
303: * Constructor for the ProfilerCmd object
304: *
305: * @param clipp
306: * Description of the Parameter
307: * @param args
308: * Description of the Parameter
309: * @exception ProfilerException
310: * Description of the Exception
311: * @since
312: */
313: public ProfilerCmd(CLIPParser clipp, String[] args)
314: throws ProfilerException {
315: parse(clipp, args);
316: }
317:
318: /**
319: * Gets the cLIPParser attribute of the ProfilerCmd class
320: *
321: * @return The cLIPParser value
322: * @exception CLIPException
323: * Description of the Exception
324: * @since
325: */
326: protected CLIPParser getCLIPParser() throws CLIPException {
327: try {
328: CLIPParser.Option[] optsRun = {
329: new CLIPParser.Option(HELP, "?",
330: CLIPParser.BOOLEAN, "false",
331: getLocalizedString("optHelp")),
332: new CLIPParser.Option(UID, "u", CLIPParser.REGULAR,
333: OPT_DEFAULT,
334: getLocalizedString("optArgUID")),
335: new CLIPParser.Option(ORGANIZATION, "o",
336: CLIPParser.REGULAR, null,
337: getLocalizedString("optOrganization")),
338: new CLIPParser.Option(PORTAL, "p",
339: CLIPParser.REGULAR, System.getProperty(
340: "PS_DEFAULT_PORTAL",
341: AdminUtil.UPGRADED_PORTAL),
342: getLocalizedString("optPortalId")),
343: new CLIPParser.Option(VERBOSE, "b",
344: CLIPParser.BOOLEAN, "false",
345: getLocalizedString("optVerbose")),
346: new CLIPParser.Option(VERSION, "V",
347: CLIPParser.BOOLEAN, "false",
348: getLocalizedString("optVersion")) };
349: CLIPParser.Option[] optsStop = {
350: new CLIPParser.Option(HELP, "?",
351: CLIPParser.BOOLEAN, "false",
352: getLocalizedString("optHelp")),
353: new CLIPParser.Option(ORGANIZATION, "o",
354: CLIPParser.REGULAR, null,
355: getLocalizedString("optOrganization")),
356: new CLIPParser.Option(PORTAL, "p",
357: CLIPParser.REGULAR, System.getProperty(
358: "PS_DEFAULT_PORTAL",
359: AdminUtil.UPGRADED_PORTAL),
360: getLocalizedString("optPortalId")),
361: new CLIPParser.Option(VERBOSE, "b",
362: CLIPParser.BOOLEAN, "false",
363: getLocalizedString("optVerbose")),
364: new CLIPParser.Option(VERSION, "V",
365: CLIPParser.BOOLEAN, "false",
366: getLocalizedString("optVersion")) };
367: CLIPParser.SubCommand scStop = new CLIPParser.SubCommand(
368: STOP, optsStop, 0, 0,
369: getLocalizedString("helpStop"), "");
370: CLIPParser.SubCommand scRun = new CLIPParser.SubCommand(
371: RUN, optsRun, 0, 0, getLocalizedString("helpRun"),
372: "");
373: CLIPParser.SubCommand[] subcmds = { scStop, scRun };
374: return new CLIPParser(Profiler.COMMANDNAME, subcmds,
375: getLocalizedString("helpCmd"));
376: } catch (Exception e) {
377: throw new CLIPException("bad getClipparser", 0);
378: }
379: }
380:
381: /* Gets the AMStoreConnection as the AdminDN from adminUtil
382: *
383: * @return The AMStoreConnection value
384: */
385: private AMStoreConnection getSSOStoreConnection() {
386: try {
387: if (sConnection == null) {
388: if (ssoToken == null) {
389: SSOTokenManager ssom = SSOTokenManager
390: .getInstance();
391: ssoToken = ssom.createSSOToken(
392: new java.security.Principal() {
393: public String getName() {
394: return AdminUtils.getAdminDN();
395: }
396: }, adminPWD);
397: }
398: sConnection = new AMStoreConnection(ssoToken);
399: }
400: return sConnection;
401: } catch (Exception e) {
402: if (getLogger().isLoggable(Level.SEVERE))
403: getLogger().log(Level.SEVERE, "PSSS_CSPPC0002", e);
404: return null;
405: }
406: }
407:
408: /**
409: * Description of the Method
410: *
411: * @exception ProfilerException
412: * Description of the Exception
413: * @since
414: */
415: public void run() throws ProfilerException {
416: if (subcmd == SUBCMD_RUN) {
417: // execution of the workers
418: try {
419: profilerProps = new Properties();
420: notifierProps = new Properties();
421: try {
422: FileInputStream fi = new FileInputStream(
423: runtimePropPath);
424: profilerProps.load(fi);
425: profilerProps.put("portalId", portalId);
426: notifierProps.load(fi);
427: notifierProps.put("portalId", portalId);
428: } catch (Exception e) {
429: getLogger().log(Level.SEVERE, "PSSS_CSPPC0012",
430: runtimePropPath);
431: profilerProps.put("profilerThread", "2");
432: profilerProps.put("notifierThread", "2");
433: profilerProps.put("identityConnectionPool", "1");
434: notifierProps.put("profilerThread", "2");
435: notifierProps.put("notifierThread", "2");
436: notifierProps.put("identityConnectionPool", "1");
437: }
438:
439: String maxHits = "4";
440: String provider = ""; // TODO if empty later will get URL exception
441: String srchServer = ""; // TODO if empty later will get URL exception in Channel
442: String smtp = ""; // TODO if empty will get Mail exception
443: String email = ""; //empty value is acceptable
444: //getting Config from Subscriptions Service
445: sConnection = getSSOStoreConnection();
446: AMOrganization amOrg = sConnection
447: .getOrganization(organization);
448: String svcPortalId = null;
449: if (portalId == null
450: || portalId.equals(AdminUtil.UPGRADED_PORTAL)) {
451: // Upgraded portal's have a subscriptions service which has a "%PORTALID% empty
452: svcPortalId = "";
453: } else {
454: svcPortalId = portalId;
455: }
456: AMTemplate orgTemplate = amOrg.getTemplate("SunPortal"
457: + svcPortalId + "SubscriptionsService",
458: AMTemplate.ORGANIZATION_TEMPLATE);
459: email = orgTemplate
460: .getStringAttribute("sunPortalProfilerEmail");
461: notifierProps.put("profilerFrom", email);
462: smtp = orgTemplate
463: .getStringAttribute("sunPortalProfilerSMTP");
464: notifierProps.put("mail.smtp.host", smtp);
465: provider = orgTemplate
466: .getStringAttribute("sunPortalProfilerProvider");
467: profilerProps.put("profilerProvider", provider);
468: srchServer = orgTemplate
469: .getStringAttribute("sunPortalProfilerDefaultSearch");
470: profilerProps.put("profilerDefaultSearchServer",
471: srchServer);
472: maxHits = orgTemplate
473: .getStringAttribute("sunPortalProfilerMaxHits");
474: profilerProps.put("profilerMaxHits", maxHits);
475: profilerProps.put("portalId", portalId);
476: // getting users
477: AMPeopleContainer amPeople = sConnection
478: .getPeopleContainer("ou=People," + organization);
479:
480: // getting subscription enabled user set
481: HashMap subsSrvHM = new HashMap();
482: Set subSrvHS = new HashSet();
483: subSrvHS.add("sunportal" + svcPortalId
484: + "pksubscriptionsperson");
485: subsSrvHM.put("objectClass", subSrvHS);
486: AMSearchControl amSrchCtrl = new AMSearchControl();
487: amSrchCtrl.setSearchScope(AMConstants.SCOPE_SUB);
488: if (uid == null || uid.equals(OPT_DEFAULT)) {
489: //all subscription enabled users within org
490: AMSearchResults amSrchRslt = amPeople.searchUsers(
491: "*", subsSrvHM, amSrchCtrl);
492: subsUserSet = Collections
493: .synchronizedSet(amSrchRslt
494: .getSearchResults());
495: if (amSrchRslt.getErrorCode() != AMSearchResults.SUCCESS) {
496: if (getLogger().isLoggable(Level.SEVERE))
497: getLogger().log(Level.SEVERE,
498: "PSSS_CSPPC0003", organization);
499: }
500: } else {
501: //only specified users via '-u' option
502: StringTokenizer st = new StringTokenizer(uid, ",");
503: subsUserSet = Collections
504: .synchronizedSet(new HashSet());
505: while (st.hasMoreTokens()) {
506: String userDN = "uid=" + st.nextToken()
507: + ",ou=People," + organization;
508: subsUserSet.add(userDN);
509: }
510: }
511:
512: // creating the queues
513: UserQueue uq = new UserQueue(subsUserSet);
514: NotificationQueue nq = new NotificationQueue();
515:
516: // creating ProfilerWorker threads
517: int nbPWT = Integer.parseInt(profilerProps.getProperty(
518: "profilerThread", "1"));
519: ArrayList pt = new ArrayList();
520: for (int p = 0; p < nbPWT; p++) {
521: ProfilerWorker pw = new ProfilerWorker(sConnection,
522: ssoToken, adminUID, adminPWD, uq, nq,
523: profilerProps, notifierProps);
524: Thread ptObj = new Thread(pw);
525: ptObj.start();
526: pt.add(ptObj);
527: }
528:
529: // creating NotificationWorker threads
530: int nbNWT = Integer.parseInt(profilerProps.getProperty(
531: "notifierThread", "1"));
532: ArrayList nt = new ArrayList();
533: for (int n = 0; n < nbNWT; n++) {
534: /*
535: NotificationWorker nw = new NotificationWorker(sConnection, uq, nq,
536: profilerProps,notifierProps, getLogger());
537: **/
538: NotificationWorker nw = new NotificationWorker(
539: sConnection, uq, nq, profilerProps,
540: notifierProps);
541: Thread ntObj = new Thread(nw);
542: ntObj.start();
543: nt.add(ntObj);
544: }
545:
546: try {
547: // watching end of profilerWorkers
548: Iterator ptIter = pt.iterator();
549: while (ptIter.hasNext()) {
550: Thread t = (Thread) ptIter.next();
551: t.join();
552: }
553: } catch (Exception e) {
554: if (getLogger().isLoggable(Level.SEVERE))
555: getLogger().log(Level.SEVERE, "PSSS_CSPPC0004",
556: e);
557: }
558:
559: // sending end of notification in the queue
560: nq.setStatus(false);
561:
562: try {
563: // watching end of notifierWorkers
564: Iterator ntIter = nt.iterator();
565: while (ntIter.hasNext()) {
566: Thread t = (Thread) ntIter.next();
567: t.join();
568: }
569: } catch (Exception e) {
570: if (getLogger().isLoggable(Level.SEVERE))
571: getLogger().log(Level.SEVERE, "PSSS_CSPPC0005",
572: e);
573: }
574: } catch (SSOException se) {
575: if (getLogger().isLoggable(Level.SEVERE))
576: getLogger().log(Level.SEVERE, "PSSS_CSPPC0006",
577: se.getMessage());
578: throw new ProfilerException(se.getMessage());
579: } catch (AMException ame) {
580: if (getLogger().isLoggable(Level.SEVERE)) {
581: getLogger().log(Level.SEVERE, "PSSS_CSPPC0007",
582: ame.getMessage());
583: }
584: throw new ProfilerException(ame.getMessage());
585: }
586: }
587: }
588:
589: /**
590: * Gets the versionInfo attribute of the ProfilerCmd object
591: *
592: * @return The versionInfo value
593: * @since
594: */
595: private String getVersionInfo() {
596: ResourceBundle prodRB = PropertyResourceBundle
597: .getBundle("PSversion");
598: StringBuffer vinfo = new StringBuffer();
599: vinfo.append(Profiler.COMMANDNAME).append(" (").append(
600: prodRB.getString("productname")).append(" ").append(
601: prodRB.getString("productversion")).append(") ")
602: .append(Profiler.COMMANDVERSION);
603: vinfo.append("\n").append(prodRB.getString("copyright"));
604: return vinfo.toString();
605: }
606:
607: /**
608: * Description of the Method
609: *
610: * @param clipp
611: * Description of the Parameter
612: * @param argv
613: * Description of the Parameter
614: * @exception ProfilerException
615: * Description of the Exception
616: * @since
617: */
618: private void parse(CLIPParser clipp, String[] argv)
619: throws ProfilerException {
620:
621: // version (before CLIP parsing begins)
622: if (clipp.needsVersion(argv)) {
623: getLogger().log(Level.INFO, getVersionInfo());
624: System.exit(0);
625: }
626:
627: // help
628: if (clipp.needsHelp(argv)) {
629: if (getLogger().isLoggable(Level.FINE))
630: getLogger().log(Level.FINE, "PSSS_CSPPC0008");
631: getLogger().log(Level.INFO, clipp.getHelp(argv));
632: System.exit(0);
633: }
634:
635: // get options
636: Map options = null;
637: try {
638: options = clipp.getOptions(argv);
639: } catch (CLIPException ce) {
640: throw new ProfilerException("errorCLIPParseError", ce);
641: }
642: try {
643: clipp.verifyArguments(argv);
644: } catch (CLIPException ce) {
645: throw new ProfilerException("errorCLIPParseError", ce);
646: }
647:
648: // verbose
649: if (((String[]) options.get(VERBOSE))[0].equals("true")) {
650: verbose = true;
651: } else {
652: verbose = false;
653: }
654:
655: // get subcommand
656: String sc = null;
657: try {
658:
659: sc = clipp.getSubCommand(argv);
660:
661: } catch (CLIPException ce) {
662: Object[] tokens = { sc };
663: throw new ProfilerException("errorInvalidSubCmd", ce,
664: tokens);
665: }
666:
667: if (sc.equals(STOP)) {
668: subcmd = SUBCMD_STOP;
669: } else if (sc.equals(RUN)) {
670: subcmd = SUBCMD_RUN;
671: }
672:
673: // required options
674: try {
675:
676: organization = ((String[]) options.get(ORGANIZATION))[0];
677:
678: if (organization.trim().length() == 0) {
679: if (getLogger().isLoggable(Level.INFO))
680: getLogger().log(Level.INFO, "PSSS_CSPPC0009");
681: throw new ProfilerException("errorNoDNOrganization");
682: }
683: } catch (NullPointerException npe) {
684: if (getLogger().isLoggable(Level.INFO))
685: getLogger().log(Level.INFO, "PSSS_CSPPC0010");
686: throw new ProfilerException("errorNoDNOrganization");
687: }
688:
689: try {
690:
691: portalId = ((String[]) options.get(PORTAL))[0];
692:
693: if (portalId != null && portalId.trim().length() == 0) {
694: // if the option is not there then we use default portal
695: portalId = System.getProperty("PS_DEFAULT_PORTAL",
696: AdminUtil.UPGRADED_PORTAL);
697: }
698: } catch (NullPointerException npe) {
699: // if the option is not there then we use default portal
700: portalId = System.getProperty("PS_DEFAULT_PORTAL",
701: AdminUtil.UPGRADED_PORTAL);
702: }
703:
704: // either DN or ORGANIZATION has to be specified
705: // can't specify both
706: try {
707:
708: uid = ((String[]) options.get(UID))[0];
709: if (portalId == null)
710: portalId = System.getProperty("PS_DEFAULT_PORTAL",
711: AdminUtil.UPGRADED_PORTAL);
712: if (uid.equals(OPT_DEFAULT) || uid == null) {
713: //calling profiler for all users within the organization
714: } else if (organization.trim().length() != 0) {
715: //calling profiling for specified users in organization
716: }
717: } catch (Exception e) {
718:
719: throw new ProfilerException(
720: "failed to get the required argument");
721: }
722:
723: // user used for profiling
724: adminUID = AdminUtils.getAdminDN();
725:
726: adminPWD = new String(AdminUtils.getAdminPassword());
727:
728: runtimePropPath = System.getProperty("PS_DATA_DIR")
729: + File.separator + "portals" + File.separator
730: + portalId + File.separator + "config" + File.separator
731: + PSConfigConstants.PS_PROFILER_CONFIG_FILE;
732:
733: }
734:
735: public static void setLocale(java.util.Locale locale) {
736: // load resource bundle based on locale
737: rb = PropertyResourceBundle.getBundle(RESOURCE_BASE, locale);
738: }
739:
740: public static String getLocalizedString(String key) {
741: return rb.getString(key);
742: }
743:
744: public static String getLocalizedString(String key, Object[] objs) {
745:
746: if (objs != null && objs.length > 0) {
747: MessageFormat mf = new MessageFormat("");
748: mf.setLocale(rb.getLocale());
749: mf.applyPattern(rb.getString(key));
750: return mf.format(objs);
751: } else {
752: return rb.getString(key);
753: }
754: }
755:
756: public Logger getLogger() {
757: return logger;
758: }
759:
760: public void setLogger(Logger logger) {
761: this.logger = logger;
762: }
763:
764: }
|