You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mb...@apache.org on 2012/11/19 04:54:40 UTC
svn commit: r1411058 [3/3] - in /commons/sandbox/privilizer/trunk: ./ ant/
ant/lib/ ant/lib/src/ ant/lib/src/main/ ant/lib/src/main/java/
ant/lib/src/main/java/org/ ant/lib/src/main/java/org/apache/
ant/lib/src/main/java/org/apache/commons/ ant/lib/src...
Added: commons/sandbox/privilizer/trunk/maven-plugin/src/main/java/org/apache/commons/privilizer/maven/WeaveMojo.java
URL: http://svn.apache.org/viewvc/commons/sandbox/privilizer/trunk/maven-plugin/src/main/java/org/apache/commons/privilizer/maven/WeaveMojo.java?rev=1411058&view=auto
==============================================================================
--- commons/sandbox/privilizer/trunk/maven-plugin/src/main/java/org/apache/commons/privilizer/maven/WeaveMojo.java (added)
+++ commons/sandbox/privilizer/trunk/maven-plugin/src/main/java/org/apache/commons/privilizer/maven/WeaveMojo.java Mon Nov 19 03:54:31 2012
@@ -0,0 +1,40 @@
+/*
+ * Copyright the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.privilizer.maven;
+
+import org.apache.commons.privilizer.Privileged;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+
+
+/**
+ * Goal to weave classes with {@link SecurityManager} handling code for methods marked with
+ * the {@link Privileged} annotation.
+ */
+@Mojo(name = "weave", defaultPhase = LifecyclePhase.PROCESS_CLASSES, requiresDependencyCollection = ResolutionScope.COMPILE)
+public class WeaveMojo extends PrivilegedMojo {
+
+ @Override
+ public void execute() throws MojoFailureException {
+ try {
+ createWeaver().weaveAll();
+ } catch (Exception e) {
+ throw new MojoFailureException("failed", e);
+ }
+ }
+}
Propchange: commons/sandbox/privilizer/trunk/maven-plugin/src/main/java/org/apache/commons/privilizer/maven/WeaveMojo.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/privilizer/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/privilizer/trunk/pom.xml?rev=1411058&view=auto
==============================================================================
--- commons/sandbox/privilizer/trunk/pom.xml (added)
+++ commons/sandbox/privilizer/trunk/pom.xml Mon Nov 19 03:54:31 2012
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright the original author or authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ --><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-sandbox-parent</artifactId>
+ <version>10-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>commons-privilizer-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>Commons Privilizer Parent POM</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <maven.compile.source>1.5</maven.compile.source>
+ <maven.compile.target>1.5</maven.compile.target>
+ <commons.componentid>privilizer</commons.componentid>
+ <commons.release.version>1.0</commons.release.version>
+ <commons.rc.version>RC1</commons.rc.version>
+ <!--commons.jira.id>PRIVILIZER</commons.jira.id>
+ <commons.jira.pid>666</commons.jira.pid-->
+ </properties>
+
+ <developers>
+ <developer>
+ <id>mbenson</id>
+ <name>Matt Benson</name>
+ <email>mbenson AT apache DOT org</email>
+ <organization>Apache</organization>
+ </developer>
+ </developers>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/commons/sandbox/privilizer/trunk/</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/sandbox/privilizer/trunk/</developerConnection>
+ <url>http://svn.apache.org/viewvc/commons/sandbox/privilizer/trunk/</url>
+ </scm>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-privilizer-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-privilizer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.10</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-privilizer-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.5.1</version>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.12.4</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-report-plugin</artifactId>
+ <version>2.12.4</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.2.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.5.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>1.7</version>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>buildhelper-maven-plugin</artifactId>
+ <version>1.7</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>jar-no-fork</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>attach-test-sources</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>test-jar-no-fork</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-site-plugin</artifactId>
+ <version>3.2</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.doxia</groupId>
+ <artifactId>doxia-module-markdown</artifactId>
+ <version>1.3</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+
+ <modules>
+ <module>api</module>
+ <module>weaver</module>
+ <module>maven-plugin</module>
+ <module>example</module>
+ <module>ant</module>
+ </modules>
+</project>
Propchange: commons/sandbox/privilizer/trunk/pom.xml
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/privilizer/trunk/src/site/markdown/index.md
URL: http://svn.apache.org/viewvc/commons/sandbox/privilizer/trunk/src/site/markdown/index.md?rev=1411058&view=auto
==============================================================================
--- commons/sandbox/privilizer/trunk/src/site/markdown/index.md (added)
+++ commons/sandbox/privilizer/trunk/src/site/markdown/index.md Mon Nov 19 03:54:31 2012
@@ -0,0 +1,49 @@
+# Commons Privilizer
+
+Provides machinery to automate the handling of Java Security access
+controls in code. This involves wrapping calls that may trigger
+`java.lang.SecurityException`s in `PrivilegedAction` objects.
+Unfortunately this is quite an expensive operation and slows code
+down considerably; when executed in an environment that has no
+`SecurityManager` activated it is an utter waste.
+The typical pattern to cope with this is:
+
+```java
+if (System.getSecurityManager() != null) {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ doSomethingThatRequiresPermissions();
+ return null;
+ }
+ });
+} else {
+ doSomethingThatRequiresPermissions();
+}
+```
+
+This becomes tedious in short order. The immediate response of a
+typical developer: relegate the repetitive code to a set of
+utility methods. In the case of Java security, however, this
+approach is considered risky. The purpose of the Privilizer, then,
+is to instrument compiled methods originally annotated with our
+`@Privileged` annotation. This annotation is retained in the
+classfiles, but not available at runtime, and there are no runtime
+dependencies.
+
+### With Privilizer
+
+```java
+
+@Privileged
+private void doSomethingThatRequiresPermissions() {
+ ...
+}
+```
+
+Commons Privilizer provides both a Maven plugin and an Antlib for
+weaving your compiled, annotated classes. You can control the weaving
+behavior by parameterizing the Maven goals and Ant task with
+the [Policy][policy] and [AccessLevel][accessLevel] `enum`s.
+
+[policy]: apidocs/org/apache/commons/privilizer/weave/Privilizer.Policy.html
+[accessLevel]: apidocs/org/apache/commons/privilizer/weave/AccessLevel.html
Added: commons/sandbox/privilizer/trunk/src/site/resources/images/privilizer-logo-white.png
URL: http://svn.apache.org/viewvc/commons/sandbox/privilizer/trunk/src/site/resources/images/privilizer-logo-white.png?rev=1411058&view=auto
==============================================================================
Binary file - no diff available.
Propchange: commons/sandbox/privilizer/trunk/src/site/resources/images/privilizer-logo-white.png
------------------------------------------------------------------------------
svn:mime-type = image/png
Added: commons/sandbox/privilizer/trunk/src/site/resources/images/privilizer-logo-white.xcf
URL: http://svn.apache.org/viewvc/commons/sandbox/privilizer/trunk/src/site/resources/images/privilizer-logo-white.xcf?rev=1411058&view=auto
==============================================================================
Binary file - no diff available.
Propchange: commons/sandbox/privilizer/trunk/src/site/resources/images/privilizer-logo-white.xcf
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: commons/sandbox/privilizer/trunk/src/site/site.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/privilizer/trunk/src/site/site.xml?rev=1411058&view=auto
==============================================================================
--- commons/sandbox/privilizer/trunk/src/site/site.xml (added)
+++ commons/sandbox/privilizer/trunk/src/site/site.xml Mon Nov 19 03:54:31 2012
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project name="Commons Privilizer">
+ <bannerRight>
+ <name>Commons Privilizer</name>
+ <src>/images/privilizer-logo-white.png</src>
+ <href>/index.html</href>
+ </bannerRight>
+ <body>
+ <menu name="Commons Privilizer">
+ <item name="Overview" href="/index.html"/>
+ <item name="Javadoc" href="apidocs/index.html"/>
+ <item name="Mailing lists" href="/mail-lists.html"/>
+ <item name="Issue Tracking" href="/issue-tracking.html"/>
+ </menu>
+ <menu name="Development">
+ <item name="Team" href="/team-list.html"/>
+ <item name="SVN" href="/source-repository.html"/>
+ </menu>
+ </body>
+</project>
Propchange: commons/sandbox/privilizer/trunk/src/site/site.xml
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/privilizer/trunk/weaver/pom.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/privilizer/trunk/weaver/pom.xml?rev=1411058&view=auto
==============================================================================
--- commons/sandbox/privilizer/trunk/weaver/pom.xml (added)
+++ commons/sandbox/privilizer/trunk/weaver/pom.xml Mon Nov 19 03:54:31 2012
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<!--
+
+ Copyright the original author or authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ -->
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-privilizer-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>commons-privilizer</artifactId>
+ <name>Commons Privilizer</name>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-privilizer-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>3.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.xbean</groupId>
+ <artifactId>xbean-finder-shaded</artifactId>
+ <version>3.12</version>
+ </dependency>
+ <dependency>
+ <groupId>org.javassist</groupId>
+ <artifactId>javassist</artifactId>
+ <version>3.16.1-GA</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.4</version>
+ </dependency>
+ </dependencies>
+</project>
Propchange: commons/sandbox/privilizer/trunk/weaver/pom.xml
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/AccessLevel.java
URL: http://svn.apache.org/viewvc/commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/AccessLevel.java?rev=1411058&view=auto
==============================================================================
--- commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/AccessLevel.java (added)
+++ commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/AccessLevel.java Mon Nov 19 03:54:31 2012
@@ -0,0 +1,56 @@
+/*
+ * Copyright the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.privilizer.weave;
+
+import java.lang.reflect.Modifier;
+import java.util.EnumSet;
+import java.util.Locale;
+
+public enum AccessLevel {
+ PUBLIC(Modifier.PUBLIC), PROTECTED(Modifier.PROTECTED), PACKAGE(0), PRIVATE(Modifier.PRIVATE);
+
+ private final int flag;
+
+ private AccessLevel(int flag) {
+ this.flag = flag;
+ }
+
+ public static AccessLevel of(int mod) {
+ if (Modifier.isPublic(mod)) {
+ return PUBLIC;
+ }
+ if (Modifier.isProtected(mod)) {
+ return PROTECTED;
+ }
+ if (Modifier.isPrivate(mod)) {
+ return PRIVATE;
+ }
+ return PACKAGE;
+ }
+
+ public int merge(int mod) {
+ int remove = 0;
+ for (AccessLevel accessLevel : EnumSet.complementOf(EnumSet.of(this))) {
+ remove |= accessLevel.flag;
+ }
+ return mod & ~remove | flag;
+ }
+
+ @Override
+ public String toString() {
+ return name().toLowerCase(Locale.US);
+ }
+}
Propchange: commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/AccessLevel.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/AlreadyWovenException.java
URL: http://svn.apache.org/viewvc/commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/AlreadyWovenException.java?rev=1411058&view=auto
==============================================================================
--- commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/AlreadyWovenException.java (added)
+++ commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/AlreadyWovenException.java Mon Nov 19 03:54:31 2012
@@ -0,0 +1,41 @@
+/*
+ * Copyright the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.privilizer.weave;
+
+import org.apache.commons.privilizer.weave.Privilizer.Policy;
+
+public class AlreadyWovenException extends IllegalStateException {
+ private static final long serialVersionUID = 1L;
+ private static final String MESSAGE = "%s already woven with policy %s";
+
+ private final String classname;
+ private final Policy policy;
+
+ public AlreadyWovenException(String classname, Policy policy) {
+ super(String.format(MESSAGE, classname, policy));
+ this.classname = classname;
+ this.policy = policy;
+ }
+
+ public String getClassname() {
+ return classname;
+ }
+
+ public Policy getPolicy() {
+ return policy;
+ }
+
+}
Propchange: commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/AlreadyWovenException.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/Body.java
URL: http://svn.apache.org/viewvc/commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/Body.java?rev=1411058&view=auto
==============================================================================
--- commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/Body.java (added)
+++ commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/Body.java Mon Nov 19 03:54:31 2012
@@ -0,0 +1,107 @@
+/*
+ * Copyright the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.privilizer.weave;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+import org.apache.commons.lang3.text.StrBuilder;
+
+class Body implements CharSequence {
+ private final String indent = " ";
+ private final StrBuilder content = new StrBuilder();
+ private int level = 0;
+ private boolean lineStarted;
+
+ {
+ startBlock();
+ }
+
+ public char charAt(int index) {
+ return content.charAt(index);
+ }
+
+ public int length() {
+ return content.length();
+ }
+
+ public CharSequence subSequence(int start, int end) {
+ return content.subSequence(start, end);
+ }
+
+ @Override
+ public String toString() {
+ return content.toString();
+ }
+
+ Body append(char c) {
+ content.append(c);
+ return this;
+ }
+
+ Body append(String format, Object... args) {
+ prepare();
+ content.append(String.format(format, args));
+ return this;
+ }
+
+ Body appendLine(String format, Object... args) {
+ return append(format, args).appendNewLine();
+ }
+
+ Body appendNewLine() {
+ content.appendNewLine();
+ lineStarted = false;
+ return this;
+ }
+
+ Body complete() {
+ try {
+ return endBlock();
+ } finally {
+ Validate.validState(level == 0);
+ }
+ }
+
+ Body endBlock() {
+ if (level < 1) {
+ throw new IllegalStateException();
+ }
+ level--;
+ prepare();
+ append('}').appendNewLine();
+ return this;
+ }
+
+ Body startBlock() {
+ if (lineStarted) {
+ append(' ');
+ }
+ level++;
+ return append('{').appendNewLine();
+ }
+
+ Body startBlock(String format, Object... args) {
+ append(format, args);
+ return startBlock();
+ }
+
+ private void prepare() {
+ if (!lineStarted) {
+ lineStarted = true;
+ content.append(StringUtils.repeat(indent, level));
+ }
+ }
+}
\ No newline at end of file
Propchange: commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/Body.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/FilesystemPrivilizer.java
URL: http://svn.apache.org/viewvc/commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/FilesystemPrivilizer.java?rev=1411058&view=auto
==============================================================================
--- commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/FilesystemPrivilizer.java (added)
+++ commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/FilesystemPrivilizer.java Mon Nov 19 03:54:31 2012
@@ -0,0 +1,166 @@
+/*
+ * Copyright the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.privilizer.weave;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.LoaderClassPath;
+import javassist.NotFoundException;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.filefilter.RegexFileFilter;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+import org.apache.commons.privilizer.Privileged;
+import org.apache.xbean.finder.AnnotationFinder;
+import org.apache.xbean.finder.archive.FileArchive;
+
+
+/**
+ * Handles weaving of methods annotated with {@link Privileged}.
+ */
+public class FilesystemPrivilizer extends Privilizer<FilesystemPrivilizer> {
+ private static ClassPool createClassPool(ClassLoader classpath, File target) {
+ final ClassPool result = new ClassPool();
+ try {
+ result.appendClassPath(validTarget(target).getAbsolutePath());
+ result.appendClassPath(new LoaderClassPath(classpath));
+ result.appendPathList(System.getProperty("java.class.path"));
+ } catch (final NotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ return result;
+ }
+
+ private static Set<Class<?>> getDeclaringClasses(Iterable<Method> methods) {
+ final Set<Class<?>> declaringClasses = new HashSet<Class<?>>();
+ for (final Method method : methods) {
+ declaringClasses.add(method.getDeclaringClass());
+ }
+ return declaringClasses;
+ }
+
+ private static Class<?> getOutermost(Class<?> type) {
+ Class<?> enclosing = type.getEnclosingClass();
+ return enclosing == null ? type : getOutermost(enclosing);
+ }
+
+ private static File validTarget(File target) {
+ Validate.notNull(target, "target");
+ Validate.isTrue(target.isDirectory(), "not a directory");
+ return target;
+ }
+
+ private final ClassLoader classpath;
+
+ private final File target;
+
+ private final ClassFileWriter classFileWriter = new ClassFileWriter() {
+ @Override
+ public void write(CtClass type) throws CannotCompileException, IOException {
+ type.writeFile(target.getAbsolutePath());
+ }
+ };
+
+ public FilesystemPrivilizer(ClassLoader classpath, File target) {
+ super(createClassPool(classpath, target));
+ this.classpath = classpath;
+ this.target = target;
+ }
+
+ public FilesystemPrivilizer(Policy policy, ClassLoader classpath, File target) {
+ super(policy, createClassPool(classpath, target));
+ this.classpath = classpath;
+ this.target = target;
+ }
+
+ /**
+ * Clear the way by deleting classfiles woven with a different
+ * {@link Policy}.
+ *
+ * @throws NotFoundException
+ */
+ public void prepare() throws NotFoundException {
+ info("preparing %s; policy = %s", target, policy);
+ final Set<File> toDelete = new TreeSet<File>();
+ for (final Class<?> type : getDeclaringClasses(findPrivilegedMethods())) {
+ final CtClass ctClass = classPool.get(type.getName());
+ final String policyValue = toString(ctClass.getAttribute(generateName(POLICY_NAME)));
+ if (policyValue == null || policyValue.equals(policy.name())) {
+ continue;
+ }
+ debug("class %s previously woven with policy %s", type.getName(), policyValue);
+ final File packageDir =
+ new File(target, StringUtils.replaceChars(ctClass.getPackageName(), '.', File.separatorChar));
+
+ // simple classname of outermost class, plus any inner classes:
+ final String pattern =
+ new StringBuilder(getOutermost(type).getSimpleName()).append("(\\$.+)??\\.class").toString();
+
+ debug("searching %s for pattern '%s'", packageDir.getAbsolutePath(), pattern);
+ toDelete.addAll(FileUtils.listFiles(packageDir, new RegexFileFilter(pattern), null));
+ }
+ if (toDelete.isEmpty()) {
+ return;
+ }
+ info("Deleting %s files...", toDelete.size());
+ debug(toDelete.toString());
+ for (File f : toDelete) {
+ if (!f.delete()) {
+ debug("Failed to delete %s", f);
+ }
+ }
+ }
+
+ /**
+ * Weave all {@link Privileged} methods found.
+ *
+ * @throws NotFoundException
+ * @throws IOException
+ * @throws CannotCompileException
+ * @throws ClassNotFoundException
+ */
+ public void weaveAll() throws NotFoundException, IOException, CannotCompileException, ClassNotFoundException {
+ int woven = 0;
+ for (final Class<?> type : getDeclaringClasses(findPrivilegedMethods())) {
+ if (weave(classPool.get(type.getName()))) {
+ woven++;
+ }
+ }
+ if (woven > 0) {
+ info("Wove %s classes.", woven);
+ }
+ }
+
+ @Override
+ protected ClassFileWriter getClassFileWriter() {
+ return classFileWriter;
+ }
+
+ private List<Method> findPrivilegedMethods() {
+ final AnnotationFinder annotationFinder = new AnnotationFinder(new FileArchive(classpath, target), false);
+ return annotationFinder.findAnnotatedMethods(Privileged.class);
+ }
+}
Propchange: commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/FilesystemPrivilizer.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/Privilizer.java
URL: http://svn.apache.org/viewvc/commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/Privilizer.java?rev=1411058&view=auto
==============================================================================
--- commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/Privilizer.java (added)
+++ commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/Privilizer.java Mon Nov 19 03:54:31 2012
@@ -0,0 +1,490 @@
+/*
+ * Copyright the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.privilizer.weave;
+
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.nio.charset.Charset;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.logging.Logger;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtMethod;
+import javassist.CtNewConstructor;
+import javassist.CtNewMethod;
+import javassist.CtPrimitiveType;
+import javassist.NotFoundException;
+import javassist.bytecode.Descriptor;
+
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+import org.apache.commons.lang3.text.StrBuilder;
+import org.apache.commons.privilizer.Privileged;
+
+
+/**
+ * Handles weaving of methods annotated with {@link Privileged}.
+ */
+public abstract class Privilizer<SELF extends Privilizer<SELF>> {
+ public interface ClassFileWriter {
+ void write(CtClass type) throws CannotCompileException, IOException;
+ }
+
+ public interface Log {
+ void debug(String message);
+
+ void verbose(String message);
+
+ void error(String message);
+
+ void info(String message);
+
+ void warn(String message);
+ }
+
+ /**
+ * Weaving policy: when to use {@link PrivilegedAction}s.
+ */
+ public enum Policy {
+ /**
+ * Disables weaving.
+ */
+ NEVER,
+
+ /**
+ * Weaves such that the check for an active {@link SecurityManager} is
+ * done once only.
+ */
+ ON_INIT(generateName("hasSecurityManager")),
+
+ /**
+ * Weaves such that the check for an active {@link SecurityManager} is
+ * done for each {@link Privileged} method execution.
+ */
+ DYNAMIC(HAS_SECURITY_MANAGER_CONDITION),
+
+ /**
+ * Weaves such that {@link Privileged} methods are always executed as
+ * such.
+ */
+ ALWAYS;
+
+ private final String condition;
+
+ private Policy() {
+ this(null);
+ }
+
+ private Policy(String condition) {
+ this.condition = condition;
+ }
+
+ private boolean isConditional() {
+ return condition != null;
+ }
+ }
+
+ protected static final String POLICY_NAME = "policyName";
+
+ private static final String ACTION_SUFFIX = "_ACTION";
+
+ private static final String GENERATE_NAME = "__privileged_%s";
+ private static final String HAS_SECURITY_MANAGER_CONDITION = "System.getSecurityManager() != null";
+
+ protected static String generateName(String simple) {
+ return String.format(GENERATE_NAME, simple);
+ }
+
+ protected static String toString(byte[] b) {
+ return b == null ? null : new String(b, Charset.forName("UTF-8"));
+ }
+
+ protected final Policy policy;
+
+ protected final ClassPool classPool;
+
+ private boolean settingsReported;
+
+ private Log log = new Log() {
+ final Logger logger = Logger.getLogger(Privilizer.class.getName());
+
+ @Override
+ public void debug(String message) {
+ logger.finer(message);
+ }
+
+ @Override
+ public void verbose(String message) {
+ logger.fine(message);
+ }
+
+ @Override
+ public void error(String message) {
+ logger.severe(message);
+ }
+
+ @Override
+ public void info(String message) {
+ logger.info(message);
+ }
+
+ @Override
+ public void warn(String message) {
+ logger.warning(message);
+ }
+
+ };
+
+ private static final Comparator<CtMethod> CTMETHOD_COMPARATOR = new Comparator<CtMethod>() {
+
+ @Override
+ public int compare(CtMethod arg0, CtMethod arg1) {
+ if (ObjectUtils.equals(arg0, arg1)) {
+ return 0;
+ }
+ if (arg0 == null) {
+ return -1;
+ }
+ if (arg1 == null) {
+ return 1;
+ }
+ final int result = ObjectUtils.compare(arg0.getName(), arg1.getName());
+ return result == 0 ? ObjectUtils.compare(arg0.getSignature(), arg1.getSignature()) : result;
+ }
+ };
+
+ private static Set<CtMethod> getPrivilegedMethods(CtClass type) throws ClassNotFoundException {
+ final TreeSet<CtMethod> result = new TreeSet<CtMethod>(CTMETHOD_COMPARATOR);
+ for (final CtMethod m : type.getDeclaredMethods()) {
+ if (Modifier.isAbstract(m.getModifiers()) || m.getAnnotation(Privileged.class) == null) {
+ continue;
+ }
+ result.add(m);
+ }
+ return result;
+ }
+
+ public Privilizer(ClassPool classPool) {
+ this(Policy.DYNAMIC, classPool);
+ }
+
+ public Privilizer(Policy policy, ClassPool classPool) {
+ this.policy = Validate.notNull(policy, "policy");
+ this.classPool = Validate.notNull(classPool, "classPool");
+ }
+
+ public SELF loggingTo(Log log) {
+ this.log = Validate.notNull(log);
+ settingsReported = false;
+ @SuppressWarnings("unchecked")
+ final SELF self = (SELF) this;
+ return self;
+ }
+
+ /**
+ * Weave the specified class.
+ *
+ * @param type
+ * @return whether any work was done
+ * @throws NotFoundException
+ * @throws IOException
+ * @throws CannotCompileException
+ * @throws ClassNotFoundException
+ */
+ public boolean weave(CtClass type) throws NotFoundException, IOException, CannotCompileException,
+ ClassNotFoundException {
+ reportSettings();
+ final String policyName = generateName(POLICY_NAME);
+ final String policyValue = toString(type.getAttribute(policyName));
+ if (policyValue != null) {
+ verbose("%s already woven with policy %s", type.getName(), policyValue);
+ if (!policy.name().equals(policyValue)) {
+ throw new AlreadyWovenException(type.getName(), Policy.valueOf(policyValue));
+ }
+ return false;
+ }
+ boolean result = false;
+ if (policy.compareTo(Policy.NEVER) > 0) {
+ if (policy == Policy.ON_INIT) {
+ debug("Initializing field %s to %s", policy.condition, HAS_SECURITY_MANAGER_CONDITION);
+ type.addField(new CtField(CtClass.booleanType, policy.condition, type),
+ CtField.Initializer.byExpr(HAS_SECURITY_MANAGER_CONDITION));
+ }
+ for (final CtMethod m : getPrivilegedMethods(type)) {
+ result |= weave(type, m);
+ }
+ if (result) {
+ type.setAttribute(policyName, policy.name().getBytes(Charset.forName("UTF-8")));
+ getClassFileWriter().write(type);
+ }
+ }
+ log.verbose(String.format(result ? "Wove class %s" : "Nothing to do for class %s", type.getName()));
+ return result;
+ }
+
+ protected void debug(String message, Object... args) {
+ log.debug(String.format(message, args));
+ }
+
+ protected void verbose(String message, Object... args) {
+ log.verbose(String.format(message, args));
+ }
+
+ protected void warn(String message, Object... args) {
+ log.warn(String.format(message, args));
+ }
+
+ protected abstract ClassFileWriter getClassFileWriter();
+
+ protected void info(String message, Object... args) {
+ log.info(String.format(message, args));
+ }
+
+ protected boolean permitMethodWeaving(AccessLevel accessLevel) {
+ return true;
+ }
+
+ private CtClass createAction(CtClass type, CtMethod impl, Class<?> iface) throws NotFoundException,
+ CannotCompileException, IOException {
+ final boolean exc = impl.getExceptionTypes().length > 0;
+
+ final CtClass actionType = classPool.get(iface.getName());
+
+ final String simpleName = generateActionClassname(impl);
+ debug("Creating action type %s for method %s", simpleName, toString(impl));
+ final CtClass result = type.makeNestedClass(simpleName, true);
+ result.addInterface(actionType);
+
+ final CtField owner;
+ if (Modifier.isStatic(impl.getModifiers())) {
+ owner = null;
+ } else {
+ owner = new CtField(type, generateName("owner"), result);
+ owner.setModifiers(Modifier.PRIVATE | Modifier.FINAL);
+ debug("Adding owner field %s to %s", owner.getName(), simpleName);
+ result.addField(owner);
+ }
+
+ final List<String> propagatedParameters = new ArrayList<String>();
+ int index = -1;
+ for (final CtClass param : impl.getParameterTypes()) {
+ final String f = String.format("arg%s", Integer.valueOf(++index));
+ final CtField fld = new CtField(param, f, result);
+ fld.setModifiers(Modifier.PRIVATE | Modifier.FINAL);
+ debug("Copying parameter %s from %s to %s.%s", index, toString(impl), simpleName, f);
+ result.addField(fld);
+ propagatedParameters.add(f);
+ }
+ {
+ final StrBuilder constructor = new StrBuilder(simpleName).append('(');
+ boolean sep = false;
+ final Body body = new Body();
+
+ for (final CtField fld : result.getDeclaredFields()) {
+ if (sep) {
+ constructor.append(", ");
+ } else {
+ sep = true;
+ }
+ constructor.append(fld.getType().getName()).append(' ').append(fld.getName());
+ body.appendLine("this.%1$s = %1$s;", fld.getName());
+ }
+ constructor.append(") ").append(body.complete());
+
+ final String c = constructor.toString();
+ debug("Creating action constructor:");
+ debug(c);
+ result.addConstructor(CtNewConstructor.make(c, result));
+ }
+ {
+ final StrBuilder run = new StrBuilder("public Object run() ");
+ if (exc) {
+ run.append("throws Exception ");
+ }
+ final Body body = new Body();
+ final CtClass rt = impl.getReturnType();
+ final boolean isVoid = rt.equals(CtClass.voidType);
+ if (!isVoid) {
+ body.append("return ");
+ }
+ final String deref = Modifier.isStatic(impl.getModifiers()) ? type.getName() : owner.getName();
+ final String call =
+ String.format("%s.%s(%s)", deref, impl.getName(), StringUtils.join(propagatedParameters, ", "));
+
+ if (!isVoid && rt.isPrimitive()) {
+ body.appendLine("%2$s.valueOf(%1$s);", call, ((CtPrimitiveType) rt).getWrapperName());
+ } else {
+ body.append(call).append(';').appendNewLine();
+
+ if (isVoid) {
+ body.appendLine("return null;");
+ }
+ }
+
+ run.append(body.complete());
+
+ final String r = run.toString();
+ debug("Creating run method:");
+ debug(r);
+ result.addMethod(CtNewMethod.make(r, result));
+ }
+ getClassFileWriter().write(result);
+ debug("Returning action type %s", result);
+ return result;
+ }
+
+ private String generateActionClassname(CtMethod m) throws NotFoundException {
+ final StringBuilder b = new StringBuilder(m.getName());
+ if (m.getParameterTypes().length > 0) {
+ b.append("$$").append(
+ StringUtils.strip(Descriptor.getParamDescriptor(m.getSignature()), "(;)").replace("[", "ARRAYOF_")
+ .replace('/', '_').replace(';', '$'));
+ }
+ return b.append(ACTION_SUFFIX).toString();
+ }
+
+ private String toString(CtMethod m) {
+ return String.format("%s%s", m.getName(), m.getSignature());
+ }
+
+ private boolean weave(CtClass type, CtMethod method) throws ClassNotFoundException, CannotCompileException,
+ NotFoundException, IOException {
+ final AccessLevel accessLevel = AccessLevel.of(method.getModifiers());
+ if (!permitMethodWeaving(accessLevel)) {
+ warn("Ignoring %s method %s.%s", accessLevel, type.getName(), toString(method));
+ return false;
+ }
+ if (AccessLevel.PACKAGE.compareTo(accessLevel) > 0) {
+ warn("Possible security leak: granting privileges to %s method %s.%s", accessLevel, type.getName(),
+ toString(method));
+ }
+ final String implName = generateName(method.getName());
+
+ final CtMethod impl = CtNewMethod.copy(method, implName, type, null);
+ impl.setModifiers(AccessLevel.PRIVATE.merge(method.getModifiers()));
+ type.addMethod(impl);
+ debug("Copied %2$s %1$s.%3$s to %4$s %1$s.%5$s", type.getName(), accessLevel, toString(method),
+ AccessLevel.PRIVATE, toString(impl));
+
+ final Body body = new Body();
+ if (policy.isConditional()) {
+ body.startBlock("if (%s)", policy.condition);
+ }
+
+ final boolean exc = method.getExceptionTypes().length > 0;
+
+ if (exc) {
+ body.startBlock("try");
+ }
+
+ final Class<?> iface = exc ? PrivilegedExceptionAction.class : PrivilegedAction.class;
+ final CtClass actionType = createAction(type, impl, iface);
+ final String action = generateName("action");
+
+ body.append("final %s %s = new %s(", iface.getName(), action, actionType.getName());
+ boolean firstParam;
+ if (Modifier.isStatic(impl.getModifiers())) {
+ firstParam = true;
+ } else {
+ body.append("$0");
+ firstParam = false;
+ }
+ for (int i = 1, sz = impl.getParameterTypes().length; i <= sz; i++) {
+ if (firstParam) {
+ firstParam = false;
+ } else {
+ body.append(", ");
+ }
+ body.append('$').append(Integer.toString(i));
+ }
+ body.appendLine(");");
+
+ final CtClass rt = method.getReturnType();
+ final boolean isVoid = rt.equals(CtClass.voidType);
+
+ final String doPrivileged = String.format("%1$s.doPrivileged(%2$s)", AccessController.class.getName(), action);
+ if (isVoid) {
+ body.append(doPrivileged).append(';').appendNewLine();
+ if (policy.isConditional()) {
+ body.appendLine("return;");
+ }
+ } else {
+ final String cast = rt.isPrimitive() ? ((CtPrimitiveType) rt).getWrapperName() : rt.getName();
+ // don't worry about wrapper NPEs because we should be simply
+ // passing back an autoboxed value, then unboxing again
+ final String result = generateName("result");
+ body.appendLine("final %1$s %3$s = (%1$s) %2$s;", cast, doPrivileged, result);
+ body.append("return %s", result);
+ if (rt.isPrimitive()) {
+ body.append(".%sValue()", rt.getName());
+ }
+ body.append(';').appendNewLine();
+ }
+
+ if (exc) {
+ body.endBlock();
+ final String e = generateName("e");
+ body.startBlock("catch (%1$s %2$s)", PrivilegedActionException.class.getName(), e).appendNewLine();
+
+ final String wrapped = generateName("wrapped");
+
+ body.appendLine("final Exception %1$s = %2$s.getCause();", wrapped, e);
+ for (final CtClass thrown : method.getExceptionTypes()) {
+ body.startBlock("if (%1$s instanceof %2$s)", wrapped, thrown.getName());
+ body.appendLine("throw (%2$s) %1$s;", wrapped, thrown.getName());
+ body.endBlock();
+ }
+ body.appendLine(
+ "throw %1$s instanceof RuntimeException ? (RuntimeException) %1$s : new RuntimeException(%1$s);",
+ wrapped);
+ body.endBlock();
+ }
+
+ if (policy.isConditional()) {
+ // close if block we opened before:
+ body.endBlock();
+ // no security manager=> just call impl:
+ if (!isVoid) {
+ body.append("return ");
+ }
+ body.appendLine("%s($$);", impl.getName());
+ }
+
+ final String block = body.complete().toString();
+ debug("Setting body of %s to:\n%s", toString(method), block);
+ method.setBody(block);
+ return true;
+ }
+
+ private void reportSettings() {
+ if (!settingsReported) {
+ settingsReported = true;
+ info("Weave policy == %s", policy);
+ }
+ }
+}
Propchange: commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/Privilizer.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/URLArray.java
URL: http://svn.apache.org/viewvc/commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/URLArray.java?rev=1411058&view=auto
==============================================================================
--- commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/URLArray.java (added)
+++ commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/URLArray.java Mon Nov 19 03:54:31 2012
@@ -0,0 +1,83 @@
+/*
+ * Copyright the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.privilizer.weave;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * {@link URL} Array utilities.
+ */
+public abstract class URLArray {
+ private URLArray() {
+ }
+
+ /**
+ * Convert an {@link Iterable} of filesystem paths.
+ *
+ * @param files
+ * @return URL[]
+ */
+ public static URL[] fromPaths(final Iterable<String> files) {
+ return fromFiles(new Iterable<File>() {
+
+ public Iterator<File> iterator() {
+ final Iterator<String> path = files.iterator();
+ return new Iterator<File>() {
+
+ public boolean hasNext() {
+ return path.hasNext();
+ }
+
+ public File next() {
+ final String p = path.next();
+ return p == null ? null : new File(p);
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ });
+ }
+
+ /**
+ * Convert an {@link Iterable} of {@link File}s.
+ *
+ * @param files
+ * @return URL[]
+ */
+ public static URL[] fromFiles(Iterable<File> files) {
+ final ArrayList<URL> result = new ArrayList<URL>();
+ for (File f : files) {
+ if (f == null) {
+ result.add(null);
+ continue;
+ }
+ try {
+ result.add(f.toURI().toURL());
+ } catch (MalformedURLException e) {
+ // this shouldn't happen
+ throw new RuntimeException(e);
+ }
+ }
+ return result.toArray(new URL[result.size()]);
+ }
+}
Propchange: commons/sandbox/privilizer/trunk/weaver/src/main/java/org/apache/commons/privilizer/weave/URLArray.java
------------------------------------------------------------------------------
svn:eol-style = native