protected PermissionCollection getPermissions(CodeSource codeSource) {
    PermissionCollection perms;
    try {
      try {
        perms = super.getPermissions(codeSource);
      } catch (SecurityException e) {
        // We lied about our CodeSource and that makes URLClassLoader unhappy.
        perms = new Permissions();
      }

      ProtectionDomain myDomain =
          AccessController.doPrivileged(
              new PrivilegedAction<ProtectionDomain>() {
                public ProtectionDomain run() {
                  return getClass().getProtectionDomain();
                }
              });
      PermissionCollection myPerms = myDomain.getPermissions();
      if (myPerms != null) {
        for (Enumeration<Permission> elements = myPerms.elements(); elements.hasMoreElements(); ) {
          perms.add(elements.nextElement());
        }
      }
    } catch (Throwable e) {
      // We lied about our CodeSource and that makes URLClassLoader unhappy.
      perms = new Permissions();
    }
    perms.setReadOnly();
    return perms;
  }
  private static void doAddGlobalTransforms(
      ASTTransformationsContext context, boolean isFirstScan) {
    final CompilationUnit compilationUnit = context.getCompilationUnit();
    GroovyClassLoader transformLoader = compilationUnit.getTransformLoader();
    Map<String, URL> transformNames = new LinkedHashMap<String, URL>();
    try {
      Enumeration<URL> globalServices =
          transformLoader.getResources(
              "META-INF/services/org.codehaus.groovy.transform.ASTTransformation");
      while (globalServices.hasMoreElements()) {
        URL service = globalServices.nextElement();
        String className;
        BufferedReader svcIn = null;
        try {
          svcIn = new BufferedReader(new InputStreamReader(service.openStream()));
          try {
            className = svcIn.readLine();
          } catch (IOException ioe) {
            compilationUnit
                .getErrorCollector()
                .addError(
                    new SimpleMessage(
                        "IOException reading the service definition at "
                            + service.toExternalForm()
                            + " because of exception "
                            + ioe.toString(),
                        null));
            continue;
          }
          Set<String> disabledGlobalTransforms =
              compilationUnit.getConfiguration().getDisabledGlobalASTTransformations();
          if (disabledGlobalTransforms == null) disabledGlobalTransforms = Collections.emptySet();
          while (className != null) {
            if (!className.startsWith("#") && className.length() > 0) {
              if (!disabledGlobalTransforms.contains(className)) {
                if (transformNames.containsKey(className)) {
                  if (!service.equals(transformNames.get(className))) {
                    compilationUnit
                        .getErrorCollector()
                        .addWarning(
                            WarningMessage.POSSIBLE_ERRORS,
                            "The global transform for class "
                                + className
                                + " is defined in both "
                                + transformNames.get(className).toExternalForm()
                                + " and "
                                + service.toExternalForm()
                                + " - the former definition will be used and the latter ignored.",
                            null,
                            null);
                  }

                } else {
                  transformNames.put(className, service);
                }
              }
            }
            try {
              className = svcIn.readLine();
            } catch (IOException ioe) {
              compilationUnit
                  .getErrorCollector()
                  .addError(
                      new SimpleMessage(
                          "IOException reading the service definition at "
                              + service.toExternalForm()
                              + " because of exception "
                              + ioe.toString(),
                          null));
              //noinspection UnnecessaryContinue
              continue;
            }
          }
        } finally {
          if (svcIn != null) svcIn.close();
        }
      }
    } catch (IOException e) {
      // FIXME the warning message will NPE with what I have :(
      compilationUnit
          .getErrorCollector()
          .addError(
              new SimpleMessage(
                  "IO Exception attempting to load global transforms:" + e.getMessage(), null));
    }
    try {
      Class.forName("java.lang.annotation.Annotation"); // test for 1.5 JVM
    } catch (Exception e) {
      // we failed, notify the user
      StringBuffer sb = new StringBuffer();
      sb.append("Global ASTTransformations are not enabled in retro builds of groovy.\n");
      sb.append("The following transformations will be ignored:");
      for (Map.Entry<String, URL> entry : transformNames.entrySet()) {
        sb.append('\t');
        sb.append(entry.getKey());
        sb.append('\n');
      }
      compilationUnit
          .getErrorCollector()
          .addWarning(
              new WarningMessage(WarningMessage.POSSIBLE_ERRORS, sb.toString(), null, null));
      return;
    }

    // record the transforms found in the first scan, so that in the 2nd scan, phase operations
    // can be added for only for new transforms that have come in
    if (isFirstScan) {
      for (Map.Entry<String, URL> entry : transformNames.entrySet()) {
        context.getGlobalTransformNames().add(entry.getKey());
      }
      addPhaseOperationsForGlobalTransforms(
          context.getCompilationUnit(), transformNames, isFirstScan);
    } else {
      Iterator<Map.Entry<String, URL>> it = transformNames.entrySet().iterator();
      while (it.hasNext()) {
        Map.Entry<String, URL> entry = it.next();
        if (!context.getGlobalTransformNames().add(entry.getKey())) {
          // phase operations for this transform class have already been added before, so remove
          // from current scan cycle
          it.remove();
        }
      }
      addPhaseOperationsForGlobalTransforms(
          context.getCompilationUnit(), transformNames, isFirstScan);
    }
  }