Just to play devil's advocate, I think you may be somewhat missing the point of a generic utility method. Generic is powerful. Now you seek to pollute that. To some extent, context specific logic belongs in the calling context.
I understand that sometimes, reality doesn't play nice, and you may need to do source dependent processing. But a lot of times, those calling contexts leave artifacts. For example, what are you setting as the value of the LeadSource field? Does it vary depending on these contexts? Are there other field indicators that can lead you to conclude which context a record was created in? My preference is to put that sort of logic in a trigger if you can conclusively determine calling context another way.
Here is the extent to which I know you can determine calling context:
Batch - System.isBatch() @future - System.isFuture() Queueable - System.isQueueable() Schedulable - System.isScheduled() Trigger - Trigger.isExecuting
As far as I know you can't tell if you are running Execute Anonymous, WebService, or Visualforce. The following might be somewhat helpful:
Visualforce - ApexPages.currentPage() != null Apex REST - RestContext.request != null
You can also get a some information by querying the AuthSession object. Not sure how reliable this approach would be but worth mention.
SELECT LoginType, SessionType FROM AuthSession WHERE UsersId = :UserInfo.getUserId() AND IsCurrent = true ORDER BY CreatedDate DESC
You could also try this strategy but it's more dubious:
try { throw new DmlException(); } catch (DmlException e) { String stackTrace = e.getStackTraceString(); if (stackTrace.contains('AnonymousBlock')) system.debug('Execute Anonymous'); // other parsing... }
If you really must determine the context, I was going to recommend something similar to what @Boris wrote up. However, in addition to setting a static variable, you could consider method overloads.
public class Utility { public static void method(List<Lead> input) { // existing logic } public static void method(List<Lead> input, /*String or Enum*/ context) { method(input); // further processing } }
Or you can at least move the context specific logic to another method to minimize the "pollution" factor:
public class Utility { public static void method(List<Lead> input) { // existing logic contextLogic(input); } static void contextLogic(List<Lead> input) { if (System.isBatch()) { batchLogic(input); } if (System.isFuture()) { futureLogic(input); } if (System.isQueueable()) { queueableLogic(input); } if (System.isScheduled()) { schedulableLogic(input); } if (Trigger.isExecuting) { triggerLogic(input); } if (ApexPages.currentPage() != null) { visualforceLogic(input); } if (RestContext.request != null) { apexRestLogic(input); } try { throw new DmlException(); // down the rabbit hole... } catch (DmlException e) { // have fun } } }