001: /*
002: *
003: * Copyright (c) 2004 SourceTap - www.sourcetap.com
004: *
005: * The contents of this file are subject to the SourceTap Public License
006: * ("License"); You may not use this file except in compliance with the
007: * License. You may obtain a copy of the License at http://www.sourcetap.com/license.htm
008: * Software distributed under the License is distributed on an "AS IS" basis,
009: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
010: * the specific language governing rights and limitations under the License.
011: *
012: * The above copyright notice and this permission notice shall be included
013: * in all copies or substantial portions of the Software.
014: *
015: */
016:
017: package com.sourcetap.sfa.replication;
018:
019: import com.sourcetap.sfa.util.*;
020:
021: import org.ofbiz.entity.*;
022: import org.ofbiz.entity.model.*;
023: import org.ofbiz.base.util.Debug;
024:
025: import java.sql.Timestamp;
026:
027: import java.util.*;
028:
029: /**
030: * This class is used for data replication.
031: *
032: * @author <a href='mailto:jnutting@sourcetap.com'>John Nutting</a>
033: */
034: public class GenericReplicator {
035: /**
036: * Debug switch
037: */
038: public static final String module = GenericReplicator.class
039: .getName();
040:
041: /**
042: * Status - Continue (success)
043: */
044: public static final int STATUS_CONTINUE = 1;
045:
046: /**
047: * Status - Canceled
048: */
049: public static final int STATUS_CANCELED = 0;
050:
051: /**
052: * Status - Error
053: */
054: public static final int STATUS_ERROR = -1;
055:
056: /**
057: * Action - Error
058: */
059: public static final int ACTION_ERROR = -1;
060:
061: /**
062: * Action - Skip
063: */
064: public static final int ACTION_SKIP = 0;
065:
066: /**
067: * Action - Insert
068: */
069: public static final int ACTION_INSERT = 1;
070:
071: /**
072: * Action - Update
073: */
074: public static final int ACTION_UPDATE = 2;
075:
076: /**
077: * Action - Delete
078: */
079: public static final int ACTION_DELETE = 3;
080:
081: /**
082: * Local delegator. This is used to connect to the local data base.
083: */
084: protected GenericDelegator localDelegator;
085:
086: /**
087: * Master delegator. This is used to connect to the master data base.
088: */
089: protected GenericDelegator masterDelegator;
090:
091: /**
092: * Constructor with no args.
093: */
094: public GenericReplicator() {
095: }
096:
097: /**
098: * Constructor with delegators.
099: */
100: public GenericReplicator(GenericDelegator localDelegator_,
101: GenericDelegator masterDelegator_) {
102: setLocalDelegator(localDelegator_);
103: setMasterDelegator(masterDelegator_);
104: }
105:
106: /**
107: * Sets the local delegator attribute.
108: *
109: * @author <a href='mailto:jnutting@sourcetap.com'>John Nutting</a>
110: *
111: * @param delegator Reference to the OFBIZ delegator being used to connect to the data base
112: *
113: */
114: public void setLocalDelegator(GenericDelegator delegator) {
115: localDelegator = delegator;
116:
117: return;
118: }
119:
120: /**
121: * Gets the local delegator attribute.
122: *
123: * @author <a href='mailto:jnutting@sourcetap.com'>John Nutting</a>
124: *
125: * @param delegator Reference to the OFBIZ delegator being used to connect to the data base
126: *
127: * @return Reference to the local delegator
128: */
129: public GenericDelegator getLocalDelegator() {
130: return localDelegator;
131: }
132:
133: /**
134: * Sets the master delegator attribute.
135: *
136: * @author <a href='mailto:jnutting@sourcetap.com'>John Nutting</a>
137: *
138: * @param delegator Reference to the OFBIZ delegator being used to connect to the data base
139: *
140: */
141: public void setMasterDelegator(GenericDelegator delegator) {
142: masterDelegator = delegator;
143:
144: return;
145: }
146:
147: /**
148: * Gets the master delegator attribute.
149: *
150: * @author <a href='mailto:jnutting@sourcetap.com'>John Nutting</a>
151: *
152: * @param delegator Reference to the OFBIZ delegator being used to connect to the data base
153: *
154: * @return Reference to the master delegator
155: */
156: public GenericDelegator getMasterDelegator() {
157: return masterDelegator;
158: }
159:
160: /**
161: * Gets the node ID under which the current machine is registered for replication
162: *
163: * @author <a href='mailto:jnutting@sourcetap.com'>John Nutting</a>
164: *
165: * @param localDelegator Generic delegator pointing to the local data base.
166: *
167: * @return Replication node ID of the local computer
168: */
169: public static String getReplNodeId(GenericDelegator localDelegator) {
170: Debug.logVerbose("[getReplNodeId] Start", module);
171:
172: HashMap codeSearchMap = new HashMap();
173: codeSearchMap.put("codeTypeId", "SYSTEM_PARAMETER");
174: codeSearchMap.put("codeId", "REPL_NODE_ID");
175:
176: try {
177: GenericValue codeGV = localDelegator.findByPrimaryKey(
178: "Code", codeSearchMap);
179:
180: if (codeGV == null) {
181: return "";
182: }
183:
184: String replNodeId = codeGV.getString("codeValue");
185:
186: if (replNodeId == null) {
187: return "";
188: }
189:
190: return replNodeId;
191: } catch (GenericEntityException e) {
192: Debug.logError(
193: "[getReplNodeId] Error looking for REPL_NODE_ID in code table: "
194: + e.getLocalizedMessage(), module);
195:
196: return "";
197: }
198: }
199:
200: /**
201: * Gets the node ID under which the current machine is registered for replication
202: *
203: * @author <a href='mailto:jnutting@sourcetap.com'>John Nutting</a>
204: *
205: * @return Replication node ID of the local computer
206: */
207: public String getReplNodeId() {
208: if (getLocalDelegator() == null) {
209: Debug.logError(
210: "[getReplNodeId] Local delegator is required.",
211: module);
212:
213: return null;
214: }
215:
216: ;
217:
218: return getReplNodeId(getLocalDelegator());
219: }
220:
221: /**
222: * Gets the ReplNode record for the current machine from the master data base.
223: *
224: * Requires that the masterDelegator argument passed to the constructor is valid.
225: * Alternatively, requires the setMasterDelegator method to have been called.
226: *
227: * @author <a href='mailto:jnutting@sourcetap.com'>John Nutting</a>
228: *
229: * @return GenericValue holding the replication node record for the local computer
230: * retrieved from the master data base.
231: */
232: public GenericValue getReplNodeGenericValue(String replNodeId) {
233:
234: if (getMasterDelegator() == null) {
235: Debug
236: .logError(
237: "GenericReplicator.getReplNodeGenericValue] Master delegator is required. Cannot get node value.",
238: module);
239:
240: return null;
241: }
242:
243: ;
244:
245: HashMap replNodeSearchMap = new HashMap();
246: replNodeSearchMap.put("replNodeId", replNodeId);
247:
248: try {
249: GenericValue replNodeGV = getMasterDelegator()
250: .findByPrimaryKey("ReplNode", replNodeSearchMap);
251:
252: return replNodeGV;
253: } catch (GenericEntityException e) {
254: Debug
255: .logError(
256: "[getReplNodeGenericValue] Error looking for "
257: + "ReplNode in master data base for replNodeId "
258: + replNodeId + ": "
259: + e.getLocalizedMessage(), module);
260:
261: return null;
262: }
263: }
264:
265: /**
266: * Determines whether the local computer is registered for replication
267: *
268: * @author <a href='mailto:jnutting@sourcetap.com'>John Nutting</a>
269: *
270: * @return True if local node is registered for replication, false otherwise
271: */
272: public static boolean getIsRegistered(GenericDelegator delegator) {
273:
274: if (getReplNodeId(delegator).equals("")) {
275: return false;
276: }
277:
278: return true;
279: }
280:
281: /**
282: * Registers the local computer for replication. Assigns the next available node ID
283: * to this computer, saves it in the system parameters in the local data base, and
284: * creates a new record in the ReplNode table in the master data base.
285: *
286: * Requires that the localDelegator and masterDelegator arguments passed to the
287: * constructor are valid. Alternatively, requires the setLocalDelegator and
288: * setMasterDelegator methods to have been called.
289: *
290: * @author <a href='mailto:jnutting@sourcetap.com'>John Nutting</a>
291: *
292: * @param replNodeName Name to be assigned to the new replication node
293: * @param ownerId The Contact ID of the user who will own the new replication node
294: * @param isActive Flag indicating whether the new replication node will participate in replication
295: *
296: * @return The new replication node ID assigned to this computer
297: */
298: public String register(String replNodeName, String ownerId,
299: boolean isActive, String userPartyId) {
300:
301: if (getLocalDelegator() == null) {
302: Debug
303: .logError(
304: "[register] Local delegator is required. Registration canceled.",
305: module);
306:
307: return "";
308: }
309:
310: ;
311:
312: if (getMasterDelegator() == null) {
313: Debug
314: .logError(
315: "[register] Master delegator is required. Registration canceled.",
316: module);
317:
318: return "";
319: }
320:
321: ;
322:
323: if ((replNodeName == null) || replNodeName.equals("")) {
324: Debug
325: .logError(
326: "[register] Node Name is required. Registration canceled.",
327: module);
328:
329: return "";
330: }
331:
332: ;
333:
334: if ((ownerId == null) || ownerId.equals("")) {
335: Debug
336: .logError(
337: "[register] ownerId is required. Registration canceled.",
338: module);
339:
340: return "";
341: }
342:
343: ;
344:
345: if ((userPartyId == null) || userPartyId.equals("")) {
346: Debug
347: .logError(
348: "[register] userPartyId is required. Registration canceled.",
349: module);
350:
351: return "";
352: }
353:
354: ;
355:
356: String replNodeId = getNextSeqId("ReplNodeId",
357: getMasterDelegator());
358:
359: if ((replNodeId == null) || replNodeId.equals("")) {
360: Debug
361: .logError(
362: "GenericReplicator.register] Could not get a new node ID. Registration canceled.",
363: module);
364:
365: return "";
366: }
367:
368: ;
369:
370: // Create a new record in the ReplNode table in the master data base.
371: Timestamp now = new Timestamp(Calendar.getInstance().getTime()
372: .getTime());
373: ModelEntity replNodeME = getMasterDelegator().getModelEntity(
374: "ReplNode");
375: GenericValue replNodeGV = new GenericValue(replNodeME);
376: replNodeGV.setDelegator(getMasterDelegator());
377: replNodeGV.set("replNodeId", replNodeId);
378: replNodeGV.set("replNodeName", replNodeName);
379: replNodeGV.set("ownerId", ownerId);
380: replNodeGV.set("isActive", new Boolean(isActive));
381: replNodeGV.set("createdDate", now);
382: replNodeGV.set("createdBy", userPartyId);
383: replNodeGV.set("modifiedDate", now);
384: replNodeGV.set("modifiedBy", userPartyId);
385:
386: try {
387: Debug
388: .logVerbose(
389: "[register] About to create ReplNode record in master data base.",
390: module);
391:
392: Vector gvv = new Vector();
393: gvv.add(replNodeGV);
394: getMasterDelegator().storeAll(gvv);
395:
396: Debug.logVerbose(
397: "[register] Successfully created ReplNode record "
398: + "in master data base.", module);
399: } catch (Exception e) {
400: Debug.logError("register] Error creating ReplNode "
401: + "record in master data base: "
402: + e.getLocalizedMessage()
403: + " Registration canceled.", module);
404:
405: return "";
406: }
407:
408: // Store the new node ID in the system parameters on the local data base.
409: ModelEntity codeME = getLocalDelegator().getModelEntity("Code");
410: GenericValue codeGV = new GenericValue(codeME);
411: codeGV.setDelegator(getLocalDelegator());
412: codeGV.set("codeTypeId", "SYSTEM_PARAMETER");
413: codeGV.set("codeId", "REPL_NODE_ID");
414: codeGV.set("codeValue", replNodeId);
415: codeGV.set("createdDate", now);
416: codeGV.set("createdBy", userPartyId);
417: codeGV.set("modifiedDate", now);
418: codeGV.set("modifiedBy", userPartyId);
419:
420: try {
421: Debug
422: .logVerbose(
423: "[register] About to create Code record in local data base.",
424: module);
425:
426: Vector gvv = new Vector();
427: gvv.add(codeGV);
428: getLocalDelegator().storeAll(gvv);
429:
430: Debug
431: .logVerbose(
432: "[register] Successfully created Code record in local data base.",
433: module);
434: } catch (Exception e) {
435: Debug.logError(
436: "GenericReplicator.register] Error storing Code "
437: + "record in local data base: "
438: + e.getLocalizedMessage()
439: + " Registration canceled.", module);
440:
441: return "";
442: }
443:
444: return replNodeId;
445: }
446:
447: /**
448: * This method updates the node record in the master data base to indicate that a successful
449: * replication has been completed.
450: *
451: * @author <a href='mailto:jnutting@sourcetap.com'>John Nutting</a>
452: *
453: * @param masterDelegator Delegator to connect to the master data base
454: * @param replNodeId Replication Node ID
455: * @param userPartyId The Party ID of the current user
456: *
457: * @return The status of the replication. Possible values: STATUS_CONTINUE, STATUS_ERROR,
458: * STATUS_CANCEL
459: */
460: public int markNodeReplicated(String replNodeId, String userPartyId) {
461:
462: if (getMasterDelegator() == null) {
463: Debug
464: .logError(
465: "[markNodeReplicated] Master delegator is required.",
466: module);
467:
468: return STATUS_ERROR;
469: }
470:
471: ;
472:
473: if ((replNodeId == null) || replNodeId.equals("")) {
474: Debug.logError("[markNodeReplicated] Node ID is required.",
475: module);
476:
477: return STATUS_ERROR;
478: }
479:
480: ;
481:
482: if ((userPartyId == null) || userPartyId.equals("")) {
483: Debug.logError(
484: "[markNodeReplicated] User Party ID is required.",
485: module);
486:
487: return STATUS_ERROR;
488: }
489:
490: ;
491:
492: // Update the node record in the master data base.
493: Timestamp now = new Timestamp(Calendar.getInstance().getTime()
494: .getTime());
495: GenericValue replNodeGV = getReplNodeGenericValue(replNodeId);
496: replNodeGV.setDelegator(getMasterDelegator());
497: replNodeGV.set("isActive", new Boolean(true));
498: replNodeGV.set("lastUpdatedDate", now);
499: replNodeGV.set("lastUpdatedBy", userPartyId);
500: replNodeGV.set("modifiedDate", now);
501: replNodeGV.set("modifiedBy", userPartyId);
502:
503: try {
504:
505: Debug.logVerbose("[markNodeReplicated] About to update "
506: + "ReplNode record in master data base.", module);
507:
508: Vector gvv = new Vector();
509: gvv.add(replNodeGV);
510: getMasterDelegator().storeAll(gvv);
511:
512: Debug.logVerbose(
513: "[markNodeReplicated] Successfully updated "
514: + "ReplNode record in master data base.",
515: module);
516: } catch (Exception e) {
517: Debug.logError(
518: "[markNodeReplicated] Error updating ReplNode "
519: + "record in master data base: "
520: + e.getLocalizedMessage(), module);
521:
522: return STATUS_ERROR;
523: }
524:
525: return STATUS_CONTINUE;
526: }
527:
528: /** Gets the next guaranteed unique seq id from the sequence with the given sequence name.
529: * if the named sequence doesn't exist, it will be created. If the local computer is
530: * registered as a replicated node, its node ID will be prepended onto the sequence to
531: * ensure uniqueness across all nodes.
532: *
533: * @author <a href='mailto:jnutting@sourcetap.com'>John Nutting</a>
534: *
535: * @param seqName The name of the sequence to get the next seq id from
536: *
537: * @return The next sequence id for the given sequence name, with the replication node ID
538: * prepended if it exists.
539: */
540: public static String getNextSeqId(String seqName,
541: GenericDelegator delegator) {
542:
543: // Get the sequence number the regular way and convert to a string.
544: String seqId = String.valueOf(delegator.getNextSeqId(seqName));
545:
546: // See if this computer is registered as a replicated node. If so, prepend the node ID
547: // onto the sequence ID.
548: String replNodeId = getReplNodeId(delegator);
549:
550: if ((replNodeId != null) && !replNodeId.equals("")) {
551: Debug.logVerbose("[getNextSeqId] Node is registered. "
552: + "Prepending node ID onto sequence number.",
553: module);
554:
555: seqId = replNodeId + "." + seqId;
556: }
557:
558: Debug
559: .logVerbose("[getNextSeqId] Sequence ID: " + seqId,
560: module);
561:
562: return seqId;
563: }
564:
565: /**
566: * Looks in the master data base for the given login ID and password
567: *
568: * Requires that the masterDelegator argument passed to the constructor is valid.
569: * Alternatively, requires the setMasterDelegator method to have been called.
570: *
571: * @author <a href='mailto:jnutting@sourcetap.com'>John Nutting</a>
572: *
573: * @return Status. Possible values: STATUS_CONTINUE (Login ID and password are valid),
574: * STATUS_CANCEL (ID or password is not correct), or STATUS_ERROR.
575: */
576: public String validateMasterLogin(String enteredUserLoginId,
577: String enteredPassword, UserInfo masterUserInfo) {
578:
579: String errorMessage = "";
580:
581: Debug.logVerbose("[validateMasterLogin] enteredUserLoginId: "
582: + enteredUserLoginId, module);
583: Debug.logVerbose("[validateMasterLogin] enteredPassword: "
584: + enteredPassword, module);
585:
586: if ((enteredUserLoginId == null)
587: || enteredUserLoginId.equals("")) {
588: errorMessage = "User ID is required.";
589: Debug.logError("[validateMasterLogin] " + errorMessage,
590: module);
591:
592: return errorMessage;
593: }
594:
595: ;
596:
597: if ((enteredPassword == null) || enteredPassword.equals("")) {
598: errorMessage = "Password is required.";
599: Debug.logError("[validateMasterLogin] " + errorMessage,
600: module);
601:
602: return errorMessage;
603: }
604:
605: ;
606:
607: if (getMasterDelegator() == null) {
608: errorMessage = "Master delegator is required.";
609: Debug.logError("[validateMasterLogin] " + errorMessage,
610: module);
611:
612: return errorMessage;
613: }
614:
615: ;
616:
617: HashMap userLoginSearchMap = new HashMap();
618: userLoginSearchMap.put("userLoginId", enteredUserLoginId);
619:
620: try {
621: List userLoginGVL = getMasterDelegator().findByAnd(
622: "UserLogin", userLoginSearchMap);
623: Iterator userLoginGVI = userLoginGVL.iterator();
624:
625: if (userLoginGVI.hasNext()) {
626: GenericValue userLoginGV = (GenericValue) userLoginGVI
627: .next();
628: String currentPassword = userLoginGV
629: .getString("currentPassword");
630:
631: if (enteredPassword.equals(currentPassword)) {
632: // Login successful.
633: String partyId = userLoginGV.getString("partyId");
634:
635: if ((partyId == null) || partyId.equals("")) {
636: errorMessage = "A problem occurred while logging in.";
637: Debug
638: .logError(
639: "[validateMasterLogin] User party ID is null.",
640: module);
641:
642: return errorMessage;
643: }
644:
645: // Get the user contact.
646: HashMap contactFindMap = new HashMap();
647: contactFindMap.put("contactId", partyId);
648:
649: try {
650: GenericValue contactGV = getMasterDelegator()
651: .findByPrimaryKey("Contact",
652: contactFindMap);
653: String roleId = (contactGV.getString("roleId") == null) ? ""
654: : contactGV.getString("roleId");
655: String accountId = (contactGV
656: .getString("accountId") == null) ? ""
657: : contactGV.getString("accountId");
658:
659: errorMessage = "A problem occurred while logging in.";
660:
661: if ((roleId == null) || roleId.equals("")) {
662: Debug
663: .logError(
664: "[validateMasterLogin] User role ID is null.",
665: module);
666:
667: return errorMessage;
668: }
669:
670: if ((accountId == null) || accountId.equals("")) {
671: Debug
672: .logError(
673: "[validateMasterLogin] User account ID is null.",
674: module);
675:
676: return errorMessage;
677: }
678:
679: masterUserInfo.setUserName(enteredUserLoginId);
680: masterUserInfo.setPartyId(partyId);
681: masterUserInfo.setRoleId(roleId);
682: masterUserInfo.setAccountId(accountId);
683:
684: return "Success";
685: } catch (GenericEntityException e) {
686: errorMessage = "Error looking for contact: "
687: + e.getLocalizedMessage();
688: Debug.logError("[validateMasterLogin] "
689: + errorMessage, module);
690:
691: return errorMessage;
692: }
693: } else {
694: // Password is not correct
695: errorMessage = "Password is not correct.";
696:
697: return errorMessage;
698: }
699: } else {
700: // Login ID was not found.
701: errorMessage = "User ID is not valid.";
702:
703: return errorMessage;
704: }
705: } catch (GenericEntityException e) {
706: errorMessage = "Error looking for user login record: "
707: + e.getLocalizedMessage();
708:
709: Debug.logError("[validateMasterLogin] " + errorMessage,
710: module);
711:
712: return errorMessage;
713: }
714: }
715: }
|