Gradle で任意の Maven 設定ファイルのローカルリポジトリ設定を適用する
Gradle のビルドスクリプトにて mavenLocal()
を使用した際、${user.home}/.m2/settings.xml
ファイルに localRepository
設定があれば、これを反映してくれますが、現時点では任意の Maven 設定ファイル (settings.xml) の localRepository を反映する方法は特に用意されていないようです。
- Gradle 1.12
任意のローカルリポジトリを使うには mavenLocal()
を使わず maven { url <リポジトリのパス> }
とすればよいだけですので、下記の方法で任意の Maven 設定ファイルの localRepository を反映できます。
- Maven 設定ファイルをコマンドライン引数 (-P) で指定できるようにする (下記サンプルでは maven.settings としています)
- Maven 設定ファイルから取り出した localRepository の値を
maven { url <ローカルリポジトリのパス> }
で設定する
とりあえず実装してみると下記のようになります。 (Maven 設定ファイルに localRepository 設定の無いケースは考慮していない点に注意)
ビルドスクリプト build.gradle
apply plugin: 'java' repositories { // プロジェクトプロパティ maven.settings の有無で処理を振り分け if (project.hasProperty('maven.settings')) { // Maven 設定ファイルをパース def xml = new XmlSlurper().parse(new File(project['maven.settings'])) maven { url xml.localRepository.text() } } else { mavenLocal() } } dependencies { ・・・ }
-P<プロジェクトプロパティ名>=<値>
オプションで Maven 設定ファイルを指定して実行します。
実行例
> gradle build -Pmaven.settings=settings.xml
Gradle を使って JAR ファイルへ AspectJ を適用
Gradle を使って既存の JAR ファイルへ AspectJ を適用してみました。
- Gradle 1.12
- AspectJ 1.8.0
Gradle 用の AspectJ プラグインとして gradle-aspectj というものがあるようですが、今回は AspectJ (aspectjtools
) に含まれている Ant 用の AjcTask (iajc) を Gradle から使う事にします。
AjcTask の利用方法
Gradle で AjcTask を使用するには Gradle ビルドスクリプト (build.gradle) で下記のように定義します。
ant.taskdef(resource: 'org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties', classpath: <aspectjtools へのパス>)
ant.iajc()
で AjcTask を利用できるようになります。
Struts の JAR ファイルへ AspectJ を適用
今回は下記のアスペクト定義を Struts 1.3.10 の JAR ファイル (struts-core-1.3.10.jar) へ適用してみる事にします。
org.apache.struts.mock パッケージを除いた org.apache.struts 以降のパッケージに属しているクラスの BeanUtils.populate()
呼び出し箇所でプロパティ名がパターンにマッチした際に IllegalArgumentException を発生させるような処理を織り込みます。
アスペクト定義 src/main/java/fits/sample/StrutsAspect.java
package fits.sample; import java.util.Map; import java.util.regex.Pattern; import org.aspectj.lang.annotation.*; import org.aspectj.lang.*; @Aspect public class StrutsAspect { private final static Pattern PATTERN = Pattern.compile("(^|\\W)[cC]lass\\W"); @Around( "call(void org.apache..BeanUtils.populate(Object, Map)) &&" + "within(org.apache.struts..*) && " + "!within(org.apache.struts.mock.*) && " + "args(bean, properties)" ) public void aroundPopulate(ProceedingJoinPoint pjp, Object bean, Map properties) throws Throwable { if (properties != null) { checkProperties(properties); pjp.proceed(); } } private void checkProperties(Map properties) { for (Object key : properties.keySet()) { String property = (String)key; if (PATTERN.matcher(property).find()) { throw new IllegalArgumentException(key + " is invalid"); } } } }
ビルドスクリプトの内容は下記のようになります。
aspectjtools のパスを取得するために configurations へ ajc を定義し、AspectJ を適用するタスクを ajc という名称で定義しました。
struts-core-1.3.10.jar へ AspectJ を適用するための依存ライブラリは、configurations.compile から取得して、ant.iajc の classpath へ設定するようにしています。
なお、commons-fileupload や servlet-api 等の依存ライブラリはアスペクト定義の内容によって代わると思います。
ビルドスクリプト build.gradle
apply plugin: 'java' repositories { mavenCentral() } configurations { ajc } dependencies { ajc "org.aspectj:aspectjtools:1.8.0" compile "org.aspectj:aspectjrt:1.8.0" compile "org.apache.struts:struts-core:1.3.10" compile 'commons-fileupload:commons-fileupload:1.3.1' compile 'javax.servlet:servlet-api:2.5' } task ajc << { ant.taskdef(resource: 'org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties', classpath: configurations.ajc.asPath) ant.iajc(outJar: "struts-core_custom.jar", source: '1.7', showWeaveInfo: 'true') { sourceroots { sourceSets.main.java.srcDirs.each { pathelement(location: it.absolutePath) } } classpath { // 依存ライブラリの設定 pathelement(location: configurations.compile.asPath) } inpath { // struts-core へのパスを設定 pathelement(location: configurations.compile.files.find { it.path.contains 'struts-core' }.absolutePath) } } }
実行結果は下記のようになり、 ActionServlet クラスと RequestUtils クラスへ StrutsAspect が適用された JAR ファイル (struts-core_custom.jar) がカレントディレクトリへ作成されます。
実行結果
> gradle ajc --info ・・・ :ajc (Thread[main,5,main]) started. :ajc Executing task ':ajc' (up-to-date check took 0.0 secs) due to: Task has not declared any outputs. [ant:iajc] weaveinfo Join point 'method-call(void org.apache.commons.beanutils.BeanUtils.populate(java.lang.Object, java.util.Map))' in Type 'org.apache.struts.action.ActionServlet' (ActionServlet.java:845) advised by around advice from 'fits.sample.StrutsAspect' (StrutsAspect.java:19) [ant:iajc] weaveinfo Join point 'method-call(void org.apache.commons.beanutils.BeanUtils.populate(java.lang.Object, java.util.Map))' in Type 'org.apache.struts.util.RequestUtils' (RequestUtils.java:473) advised by around advice from 'fits.sample.StrutsAspect' (StrutsAspect.java:19) :ajc (Thread[main,5,main]) completed. Took 5.211 secs. BUILD SUCCESSFUL
今回使用したサンプルのソースは http://github.com/fits/try_samples/tree/master/blog/20140518/