Author: mbenson Date: Wed Dec 16 17:15:51 2015 New Revision: 1720392 URL: http://svn.apache.org/viewvc?rev=1720392&view=rev Log: formalize the 'weave lifecycle' and build upon that to introduce a provider dependency mechanism
Added: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/Consumes.java (with props) commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/ProcessorBase.java (with props) commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/Produces.java (with props) commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/ commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/WeaveLifecycle.java (with props) commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/WeaveLifecycleToken.java (with props) commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/package-info.java (with props) commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/spi/WeaveLifecycleProvider.java (with props) commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/utils/Providers.java (with props) commons/proper/weaver/trunk/processor/src/test/java/org/apache/commons/weaver/utils/ProvidersTest.java (with props) Modified: commons/proper/weaver/trunk/ant/pom.xml commons/proper/weaver/trunk/parent/ (props changed) commons/proper/weaver/trunk/parent/pom.xml commons/proper/weaver/trunk/processor/pom.xml commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/CleanProcessor.java commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/WeaveProcessor.java commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/spi/Cleaner.java commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/spi/Weaver.java Modified: commons/proper/weaver/trunk/ant/pom.xml URL: http://svn.apache.org/viewvc/commons/proper/weaver/trunk/ant/pom.xml?rev=1720392&r1=1720391&r2=1720392&view=diff ============================================================================== --- commons/proper/weaver/trunk/ant/pom.xml (original) +++ commons/proper/weaver/trunk/ant/pom.xml Wed Dec 16 17:15:51 2015 @@ -49,7 +49,6 @@ under the License. <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> - <version>3.1</version> </dependency> <dependency> <groupId>org.apache.ant</groupId> @@ -115,21 +114,25 @@ under the License. <relocations> <relocation> - <pattern>org.apache.commons.lang3.</pattern> - <shadedPattern>org.apache.commons.weaver.ant._lang3.</shadedPattern> + <pattern>org.apache.commons.collections4.</pattern> + <shadedPattern>org.apache.commons.weaver.ant._collections4.</shadedPattern> </relocation> <relocation> <pattern>org.apache.commons.io.</pattern> <shadedPattern>org.apache.commons.weaver.ant._io.</shadedPattern> </relocation> <relocation> + <pattern>org.apache.commons.lang3.</pattern> + <shadedPattern>org.apache.commons.weaver.ant._lang3.</shadedPattern> + </relocation> + <relocation> <pattern>org.apache.xbean.</pattern> <shadedPattern>org.apache.commons.weaver.ant._xbean.</shadedPattern> </relocation> </relocations> <filters> <filter> - <artifact>org.apache.commons:commons-lang3</artifact> + <artifact>org.apache.commons:commons-collections4</artifact> <excludes> <exclude>META-INF/**</exclude> </excludes> @@ -139,6 +142,12 @@ under the License. <excludes> <exclude>META-INF/**</exclude> </excludes> + </filter> + <filter> + <artifact>org.apache.commons:commons-lang3</artifact> + <excludes> + <exclude>META-INF/**</exclude> + </excludes> </filter> <filter> <artifact>org.apache.xbean:*</artifact> Propchange: commons/proper/weaver/trunk/parent/ ------------------------------------------------------------------------------ --- svn:ignore (original) +++ svn:ignore Wed Dec 16 17:15:51 2015 @@ -1 +1,3 @@ +.project +.settings target Modified: commons/proper/weaver/trunk/parent/pom.xml URL: http://svn.apache.org/viewvc/commons/proper/weaver/trunk/parent/pom.xml?rev=1720392&r1=1720391&r2=1720392&view=diff ============================================================================== --- commons/proper/weaver/trunk/parent/pom.xml (original) +++ commons/proper/weaver/trunk/parent/pom.xml Wed Dec 16 17:15:51 2015 @@ -37,6 +37,7 @@ under the License. <ant.version>1.9.4</ant.version> <checkstyle.version>2.11</checkstyle.version> + <hamcrest.version>1.3</hamcrest.version> </properties> <scm> @@ -160,6 +161,11 @@ under the License. <version>3.3.2</version> </dependency> <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-collections4</artifactId> + <version>4.1</version> + </dependency> + <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> @@ -200,6 +206,18 @@ under the License. <version>4.11</version> <scope>test</scope> </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-core</artifactId> + <version>${hamcrest.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-library</artifactId> + <version>${hamcrest.version}</version> + <scope>test</scope> + </dependency> </dependencies> </dependencyManagement> Modified: commons/proper/weaver/trunk/processor/pom.xml URL: http://svn.apache.org/viewvc/commons/proper/weaver/trunk/processor/pom.xml?rev=1720392&r1=1720391&r2=1720392&view=diff ============================================================================== --- commons/proper/weaver/trunk/processor/pom.xml (original) +++ commons/proper/weaver/trunk/processor/pom.xml Wed Dec 16 17:15:51 2015 @@ -50,10 +50,19 @@ under the License. <artifactId>commons-lang3</artifactId> </dependency> <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-collections4</artifactId> + </dependency> + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-library</artifactId> + <scope>test</scope> + </dependency> </dependencies> <build> <plugins> Modified: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/CleanProcessor.java URL: http://svn.apache.org/viewvc/commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/CleanProcessor.java?rev=1720392&r1=1720391&r2=1720392&view=diff ============================================================================== --- commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/CleanProcessor.java (original) +++ commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/CleanProcessor.java Wed Dec 16 17:15:51 2015 @@ -20,8 +20,6 @@ package org.apache.commons.weaver; import java.io.File; import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Properties; @@ -29,65 +27,39 @@ import java.util.ServiceLoader; import java.util.Set; import java.util.logging.Logger; -import org.apache.commons.lang3.Validate; +import org.apache.commons.weaver.lifecycle.WeaveLifecycle; import org.apache.commons.weaver.model.WeaveEnvironment; import org.apache.commons.weaver.spi.Cleaner; import org.apache.commons.weaver.utils.URLArray; import org.apache.xbean.finder.archive.FileArchive; /** - * This class discovers and invokes available {@link Cleaner} plugins. + * Implements {@link WeaveLifecycle#CLEAN}. */ -public class CleanProcessor { - private static final Logger LOG = Logger.getLogger(CleanProcessor.class.getName()); +public class CleanProcessor extends ProcessorBase<Cleaner> { /** - * List of picked up cleaner plugins. + * Create a new {@link CleanProcessor} instance using the {@link ServiceLoader} mechanism. + * + * @param classpath not {@code null} + * @param target not {@code null} + * @param configuration not {@code null} */ - private static final List<Cleaner> CLEANERS; - - static { - final List<Cleaner> cleaners = new ArrayList<Cleaner>(); - final ClassLoader cleanerLoader = Cleaner.class.getClassLoader(); - if (!Thread.currentThread().getContextClassLoader().equals(cleanerLoader)) { - for (final Cleaner cleaner : ServiceLoader.load(Cleaner.class, cleanerLoader)) { - cleaners.add(cleaner); - } - } - for (final Cleaner cleaner : ServiceLoader.load(Cleaner.class)) { - cleaners.add(cleaner); - } - CLEANERS = Collections.unmodifiableList(cleaners); + public CleanProcessor(final List<String> classpath, final File target, final Properties configuration) { + this(classpath, target, configuration, getServiceInstances(Cleaner.class)); } /** - * The classpath which will be used to look up cross references during cleaning. - */ - private final List<String> classpath; - - /** - * The actual path to be woven, replacing any affected classes. - */ - private final File target; - - /** - * Properties for configuring discovered plugin modules. - */ - private final Properties configuration; - - /** * Create a new {@link CleanProcessor} instance. * * @param classpath not {@code null} * @param target not {@code null} * @param configuration not {@code null} + * @param providers not (@code null} */ - public CleanProcessor(final List<String> classpath, final File target, final Properties configuration) { - super(); - this.classpath = Validate.notNull(classpath, "classpath"); - this.target = Validate.notNull(target, "target"); - Validate.isTrue(!target.exists() || target.isDirectory(), "%s is not a directory", target); - this.configuration = Validate.notNull(configuration, "configuration"); + public CleanProcessor(final List<String> classpath, final File target, final Properties configuration, + final Iterable<Cleaner> providers) { + super(classpath, target, configuration, providers); } /** @@ -95,17 +67,16 @@ public class CleanProcessor { */ public void clean() { if (!target.exists()) { - LOG.warning("Target directory " + target + " does not exist; nothing to do!"); + log.warning("Target directory " + target + " does not exist; nothing to do!"); } final Set<String> finderClasspath = new LinkedHashSet<String>(); finderClasspath.add(target.getAbsolutePath()); finderClasspath.addAll(classpath); final ClassLoader classLoader = new URLClassLoader(URLArray.fromPaths(finderClasspath)); final Finder finder = new Finder(new FileArchive(classLoader, target)); - for (final Cleaner cleaner : CLEANERS) { - final WeaveEnvironment env = - new LocalWeaveEnvironment(target, classLoader, configuration, Logger.getLogger(cleaner.getClass() - .getName())); + for (final Cleaner cleaner : providers) { + final WeaveEnvironment env = new LocalWeaveEnvironment(target, classLoader, configuration, + Logger.getLogger(cleaner.getClass().getName())); cleaner.clean(env, finder); } } Added: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/Consumes.java URL: http://svn.apache.org/viewvc/commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/Consumes.java?rev=1720392&view=auto ============================================================================== --- commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/Consumes.java (added) +++ commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/Consumes.java Wed Dec 16 17:15:51 2015 @@ -0,0 +1,44 @@ +/* + * 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. + */ +package org.apache.commons.weaver; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.apache.commons.weaver.spi.WeaveLifecycleProvider; + +/** + * Mark a {@link WeaveLifecycleProvider} as consuming the output of additional + * {@link WeaveLifecycleProvider}es of the same broad type. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Inherited +public @interface Consumes { + /** + * The consumed types. + * @return Class[] + */ + Class<? extends WeaveLifecycleProvider<?>>[] value(); +} Propchange: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/Consumes.java ------------------------------------------------------------------------------ svn:executable = * Added: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/ProcessorBase.java URL: http://svn.apache.org/viewvc/commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/ProcessorBase.java?rev=1720392&view=auto ============================================================================== --- commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/ProcessorBase.java (added) +++ commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/ProcessorBase.java Wed Dec 16 17:15:51 2015 @@ -0,0 +1,104 @@ +/* + * 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. + */ +package org.apache.commons.weaver; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Properties; +import java.util.ServiceLoader; +import java.util.logging.Logger; + +import org.apache.commons.lang3.Validate; +import org.apache.commons.weaver.lifecycle.WeaveLifecycle; +import org.apache.commons.weaver.spi.WeaveLifecycleProvider; +import org.apache.commons.weaver.utils.Providers; + +/** + * Base implementor of a {@link WeaveLifecycle} stage. + * + * @param <P> managed {@link WeaveLifecycleProvider} type + */ +class ProcessorBase<P extends WeaveLifecycleProvider<?>> { + + /** + * Use the {@link ServiceLoader} to discover available {@code type} implementations. + * + * @param type not {@code null} + * @return {@link Iterable} of {@code T} + */ + static <T> Iterable<T> getServiceInstances(final Class<T> type) { + Validate.notNull(type); + final List<T> result = new ArrayList<T>(); + final ClassLoader typeLoader = type.getClassLoader(); + if (!Thread.currentThread().getContextClassLoader().equals(typeLoader)) { + for (final T t : ServiceLoader.load(type, typeLoader)) { + result.add(t); + } + } + for (final T t : ServiceLoader.load(type)) { + result.add(t); + } + return Collections.unmodifiableList(result); + } + + /** + * Logger instance. + */ + protected final Logger log = Logger.getLogger(getClass().getName()); + + /** + * The classpath which will be used to look up cross references during weaving. + */ + protected final List<String> classpath; + + /** + * The actual path to be woven, replacing any affected classes. + */ + protected final File target; + + /** + * Properties for configuring discovered plugin modules. + */ + protected final Properties configuration; + + /** + * The managed {@link WeaveLifecycleProvider}es. + */ + protected final Iterable<P> providers; + + /** + * Create a new {@link ProcessorBase} instance. + * + * @param classpath not {@code null} + * @param target not {@code null} + * @param configuration not {@code null} + * @param providers not empty + */ + protected ProcessorBase(final List<String> classpath, final File target, final Properties configuration, + final Iterable<P> providers) { + this.classpath = Validate.notNull(classpath, "classpath"); + this.target = Validate.notNull(target, "target"); + Validate.isTrue(!target.exists() || target.isDirectory(), "%s is not a directory", target); + this.configuration = Validate.notNull(configuration, "configuration"); + this.providers = Providers.sort(providers); + } + +} Propchange: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/ProcessorBase.java ------------------------------------------------------------------------------ svn:executable = * Added: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/Produces.java URL: http://svn.apache.org/viewvc/commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/Produces.java?rev=1720392&view=auto ============================================================================== --- commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/Produces.java (added) +++ commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/Produces.java Wed Dec 16 17:15:51 2015 @@ -0,0 +1,44 @@ +/* + * 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. + */ +package org.apache.commons.weaver; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.apache.commons.weaver.spi.WeaveLifecycleProvider; + +/** + * Mark a {@link WeaveLifecycleProvider} as creating output that is consumed by additional + * {@link WeaveLifecycleProvider}es of the same broad type. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Inherited +public @interface Produces { + /** + * The consuming types. + * @return Class[] + */ + Class<? extends WeaveLifecycleProvider<?>>[] value(); +} Propchange: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/Produces.java ------------------------------------------------------------------------------ svn:executable = * Modified: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/WeaveProcessor.java URL: http://svn.apache.org/viewvc/commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/WeaveProcessor.java?rev=1720392&r1=1720391&r2=1720392&view=diff ============================================================================== --- commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/WeaveProcessor.java (original) +++ commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/WeaveProcessor.java Wed Dec 16 17:15:51 2015 @@ -20,8 +20,6 @@ package org.apache.commons.weaver; import java.io.File; import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Properties; @@ -29,66 +27,39 @@ import java.util.ServiceLoader; import java.util.Set; import java.util.logging.Logger; -import org.apache.commons.lang3.Validate; +import org.apache.commons.weaver.lifecycle.WeaveLifecycle; import org.apache.commons.weaver.model.WeaveEnvironment; import org.apache.commons.weaver.spi.Weaver; import org.apache.commons.weaver.utils.URLArray; import org.apache.xbean.finder.archive.FileArchive; /** - * This class discovers and invokes available {@link Weaver} plugins. + * Implements {@link WeaveLifecycle#WEAVE}. */ -public class WeaveProcessor { - - private static final Logger LOG = Logger.getLogger(WeaveProcessor.class.getName()); +public class WeaveProcessor extends ProcessorBase<Weaver> { /** - * List of picked up weaver plugins. + * Create a new {@link WeaveProcessor} instance using the {@link ServiceLoader} mechanism. + * + * @param classpath not {@code null} + * @param target not {@code null} + * @param configuration not {@code null} */ - private static final List<Weaver> WEAVERS; - - static { - final List<Weaver> weavers = new ArrayList<Weaver>(); - final ClassLoader weaverLoader = Weaver.class.getClassLoader(); - if (!Thread.currentThread().getContextClassLoader().equals(weaverLoader)) { - for (final Weaver weaver : ServiceLoader.load(Weaver.class, weaverLoader)) { - weavers.add(weaver); - } - } - for (final Weaver weaver : ServiceLoader.load(Weaver.class)) { - weavers.add(weaver); - } - WEAVERS = Collections.unmodifiableList(weavers); + public WeaveProcessor(final List<String> classpath, final File target, final Properties configuration) { + super(classpath, target, configuration, getServiceInstances(Weaver.class)); } /** - * The classpath which will be used to look up cross references during weaving. - */ - private final List<String> classpath; - - /** - * The actual path to be woven, replacing any affected classes. - */ - private final File target; - - /** - * Properties for configuring discovered plugin modules. - */ - private final Properties configuration; - - /** * Create a new {@link WeaveProcessor} instance. * * @param classpath not {@code null} * @param target not {@code null} * @param configuration not {@code null} + * @param providers not (@code null} */ - public WeaveProcessor(final List<String> classpath, final File target, final Properties configuration) { - super(); - this.classpath = Validate.notNull(classpath, "classpath"); - this.target = Validate.notNull(target, "target"); - Validate.isTrue(!target.exists() || target.isDirectory(), "%s is not a directory", target); - this.configuration = Validate.notNull(configuration, "configuration"); + public WeaveProcessor(final List<String> classpath, final File target, final Properties configuration, + final Iterable<Weaver> providers) { + super(classpath, target, configuration, providers); } /** @@ -96,17 +67,16 @@ public class WeaveProcessor { */ public void weave() { if (!target.exists()) { - LOG.warning("Target directory " + target + " does not exist; nothing to do!"); + log.warning("Target directory " + target + " does not exist; nothing to do!"); } final Set<String> finderClasspath = new LinkedHashSet<String>(); finderClasspath.add(target.getAbsolutePath()); finderClasspath.addAll(classpath); final ClassLoader classLoader = new URLClassLoader(URLArray.fromPaths(finderClasspath)); final Finder finder = new Finder(new FileArchive(classLoader, target)); - for (final Weaver weaver : WEAVERS) { - final WeaveEnvironment env = - new LocalWeaveEnvironment(target, classLoader, configuration, Logger.getLogger(weaver.getClass() - .getName())); + for (final Weaver weaver : providers) { + final WeaveEnvironment env = new LocalWeaveEnvironment(target, classLoader, configuration, + Logger.getLogger(weaver.getClass().getName())); weaver.process(env, finder); } } Added: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/WeaveLifecycle.java URL: http://svn.apache.org/viewvc/commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/WeaveLifecycle.java?rev=1720392&view=auto ============================================================================== --- commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/WeaveLifecycle.java (added) +++ commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/WeaveLifecycle.java Wed Dec 16 17:15:51 2015 @@ -0,0 +1,28 @@ +/* + * 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. + */ + +package org.apache.commons.weaver.lifecycle; + +/** + * Defines the parts of the weave lifecycle. + * @since 1.2 + */ +public enum WeaveLifecycle { + CLEAN, WEAVE; +} Propchange: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/WeaveLifecycle.java ------------------------------------------------------------------------------ svn:executable = * Added: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/WeaveLifecycleToken.java URL: http://svn.apache.org/viewvc/commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/WeaveLifecycleToken.java?rev=1720392&view=auto ============================================================================== --- commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/WeaveLifecycleToken.java (added) +++ commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/WeaveLifecycleToken.java Wed Dec 16 17:15:51 2015 @@ -0,0 +1,56 @@ +/* + * 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. + */ +package org.apache.commons.weaver.lifecycle; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Defines token classes corresponding to the elements of the {@link WeaveLifecycle}. + * + * @since 1.2 + */ +public class WeaveLifecycleToken { + /** + * Declares the association between a {@link WeaveLifecycleToken} and an element of the {@link WeaveLifecycle}. + */ + @Documented + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface Represents { + WeaveLifecycle value(); + } + + /** + * Represents {@link WeaveLifecycle#CLEAN}. + */ + @Represents(WeaveLifecycle.CLEAN) + public static final class Clean extends WeaveLifecycleToken { + } + + /** + * Represents {@link WeaveLifecycle#WEAVE}. + */ + @Represents(WeaveLifecycle.WEAVE) + public static final class Weave extends WeaveLifecycleToken { + } +} Propchange: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/WeaveLifecycleToken.java ------------------------------------------------------------------------------ svn:executable = * Added: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/package-info.java URL: http://svn.apache.org/viewvc/commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/package-info.java?rev=1720392&view=auto ============================================================================== --- commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/package-info.java (added) +++ commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/package-info.java Wed Dec 16 17:15:51 2015 @@ -0,0 +1,23 @@ +/* + * 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. + */ +/** + * Weave lifecycle package. + * @since 1.2 + */ +package org.apache.commons.weaver.lifecycle; \ No newline at end of file Propchange: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/lifecycle/package-info.java ------------------------------------------------------------------------------ svn:executable = * Modified: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/spi/Cleaner.java URL: http://svn.apache.org/viewvc/commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/spi/Cleaner.java?rev=1720392&r1=1720391&r2=1720392&view=diff ============================================================================== --- commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/spi/Cleaner.java (original) +++ commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/spi/Cleaner.java Wed Dec 16 17:15:51 2015 @@ -18,16 +18,19 @@ */ package org.apache.commons.weaver.spi; +import org.apache.commons.weaver.lifecycle.WeaveLifecycle; +import org.apache.commons.weaver.lifecycle.WeaveLifecycleToken.Clean; import org.apache.commons.weaver.model.Scanner; import org.apache.commons.weaver.model.WeaveEnvironment; /** - * SPI to provide a means for a weaver module to remove woven classes during - * incremental builds, if necessary. + * SPI to provide a means for a weaver module to remove woven classes during incremental builds, if necessary. + * Implements the {@code CLEAN} stage of the {@link WeaveLifecycle}. */ -public interface Cleaner { +public interface Cleaner extends WeaveLifecycleProvider<Clean> { /** * Using the supplied {@link Scanner}, clean a {@link WeaveEnvironment}. + * * @param environment to use * @param scanner to use * @return whether any work was done. Added: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/spi/WeaveLifecycleProvider.java URL: http://svn.apache.org/viewvc/commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/spi/WeaveLifecycleProvider.java?rev=1720392&view=auto ============================================================================== --- commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/spi/WeaveLifecycleProvider.java (added) +++ commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/spi/WeaveLifecycleProvider.java Wed Dec 16 17:15:51 2015 @@ -0,0 +1,28 @@ +/* + * 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. + */ +package org.apache.commons.weaver.spi; + +import org.apache.commons.weaver.lifecycle.WeaveLifecycleToken; + +/** + * Marker interface for commmons-weaver processes. + * @since 1.2 + */ +public interface WeaveLifecycleProvider<S extends WeaveLifecycleToken> { +} Propchange: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/spi/WeaveLifecycleProvider.java ------------------------------------------------------------------------------ svn:executable = * Modified: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/spi/Weaver.java URL: http://svn.apache.org/viewvc/commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/spi/Weaver.java?rev=1720392&r1=1720391&r2=1720392&view=diff ============================================================================== --- commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/spi/Weaver.java (original) +++ commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/spi/Weaver.java Wed Dec 16 17:15:51 2015 @@ -18,16 +18,19 @@ */ package org.apache.commons.weaver.spi; +import org.apache.commons.weaver.lifecycle.WeaveLifecycle; +import org.apache.commons.weaver.lifecycle.WeaveLifecycleToken.Weave; import org.apache.commons.weaver.model.Scanner; import org.apache.commons.weaver.model.WeaveEnvironment; /** - * A {@link Weaver} implementation performs the byte code enhancement in the - * classes. + * A {@link Weaver} implementation implements the {@code WEAVE} stage of the {@link WeaveLifecycle} by performing the + * byte code enhancement in the classes. */ -public interface Weaver { +public interface Weaver extends WeaveLifecycleProvider<Weave> { /** * Using the supplied {@link Scanner}, process a {@link WeaveEnvironment}. + * * @param environment to use * @param scanner to use * @return whether any work was done. Added: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/utils/Providers.java URL: http://svn.apache.org/viewvc/commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/utils/Providers.java?rev=1720392&view=auto ============================================================================== --- commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/utils/Providers.java (added) +++ commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/utils/Providers.java Wed Dec 16 17:15:51 2015 @@ -0,0 +1,210 @@ +/* + * 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. + */ +package org.apache.commons.weaver.utils; + +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Collections; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.collections4.Factory; +import org.apache.commons.collections4.map.LazyMap; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.Validate; +import org.apache.commons.weaver.Consumes; +import org.apache.commons.weaver.Produces; +import org.apache.commons.weaver.spi.WeaveLifecycleProvider; + +/** + * Utility for working with {@link WeaveLifecycleProvider} types. + */ +public final class Providers { + private enum State { + VISITING, VISITED; + } + + /** + * Sort the specified providers with respect to declared {@link Consumes} and {@link Produces} annotations. + * + * @param providers + * @return {@link Iterable} of {@code P} + */ + @SuppressWarnings("rawtypes") + public static <P extends WeaveLifecycleProvider<?>> Iterable<P> sort(final Iterable<P> providers) { + Validate.noNullElements(providers); + + final Map<Class<? extends WeaveLifecycleProvider>, Set<Class<? extends WeaveLifecycleProvider>>> dependencyMap = + toDependencyMap(providers); + + final Collection<Class<? extends WeaveLifecycleProvider>> order = + new LinkedHashSet<Class<? extends WeaveLifecycleProvider>>(); + + final Map<Class<? extends WeaveLifecycleProvider>, State> stateMap = + new HashMap<Class<? extends WeaveLifecycleProvider>, Providers.State>(); + final Deque<Class<? extends WeaveLifecycleProvider>> visiting = + new ArrayDeque<Class<? extends WeaveLifecycleProvider>>(); + + for (Class<? extends WeaveLifecycleProvider> type : dependencyMap.keySet()) { + final State state = stateMap.get(type); + + if (state == null) { + tsort(type, dependencyMap, stateMap, visiting, order); + } else if (state == State.VISITING) { + throw new RuntimeException("Unexpected node in visiting state: " + type); + } + } + + return imposeOrder(providers, order); + } + + /** + * Adapted from Apache Ant's target sorting mechanism. + * + * @param root current provider type + * @param dependencyMap {@link Map} of provider type to dependencies + * @param stateMap {@link Map} of current visitation state + * @param visiting {@link Deque} used as a stack + * @param target destination {@link Collection} which must preserve order + */ + @SuppressWarnings("rawtypes") + private static <P extends WeaveLifecycleProvider<?>> void tsort(final Class<? extends WeaveLifecycleProvider> root, + final Map<Class<? extends WeaveLifecycleProvider>, Set<Class<? extends WeaveLifecycleProvider>>> dependencyMap, + final Map<Class<? extends WeaveLifecycleProvider>, State> stateMap, + final Deque<Class<? extends WeaveLifecycleProvider>> visiting, + final Collection<Class<? extends WeaveLifecycleProvider>> target) { + + stateMap.put(root, State.VISITING); + visiting.push(root); + + for (Class<? extends WeaveLifecycleProvider> dependency : dependencyMap.get(root)) { + final State state = stateMap.get(dependency); + if (state == State.VISITED) { + continue; + } + Validate.validState(state == null, "Circular dependency: %s of %s", dependency.getName(), root.getName()); + tsort(dependency, dependencyMap, stateMap, visiting, target); + } + final Class<? extends WeaveLifecycleProvider> top = visiting.pop(); + Validate.validState(top == root, "Stack out of balance: expected %s, found %s", root.getName(), top.getName()); + + stateMap.put(root, State.VISITED); + target.add(root); + } + + /** + * Read any {@link Produces} annotation associated with {@code providerClass}, designating types before which it + * should be invoked. + * + * @param providerClass + * @return {@link Class}[] + */ + private static <P extends WeaveLifecycleProvider<?>> Class<? extends P>[] producedBy( + final Class<? extends P> providerClass) { + Validate.notNull(providerClass); + final Produces produces = providerClass.getAnnotation(Produces.class); + if (produces == null || produces.value().length == 0) { + @SuppressWarnings("unchecked") + final Class<? extends P>[] empty = (Class<? extends P>[]) ArrayUtils.EMPTY_CLASS_ARRAY; + return empty; + } + @SuppressWarnings("unchecked") + final Class<? extends P>[] result = (Class<? extends P>[]) produces.value(); + return result; + } + + /** + * Read any {@link Consumes} annotation associated with {@code providerClass} as dependencies. + * + * @param providerClass + * @return {@link Class}[] + */ + private static <P extends WeaveLifecycleProvider<?>> Class<? extends P>[] consumedBy( + final Class<? extends P> providerClass) { + Validate.notNull(providerClass); + final Consumes consumes = providerClass.getAnnotation(Consumes.class); + if (consumes == null || consumes.value().length == 0) { + @SuppressWarnings("unchecked") + final Class<? extends P>[] empty = (Class<? extends P>[]) ArrayUtils.EMPTY_CLASS_ARRAY; + return empty; + } + @SuppressWarnings("unchecked") + final Class<? extends P>[] result = (Class<? extends P>[]) consumes.value(); + return result; + } + + /** + * Create a {@link Map} of provider type to dependency types. + * + * @param providers to inspect + * @return {@link Map} + */ + @SuppressWarnings("rawtypes") + private static Map<Class<? extends WeaveLifecycleProvider>, Set<Class<? extends WeaveLifecycleProvider>>> toDependencyMap( + final Iterable<? extends WeaveLifecycleProvider<?>> providers) { + + final Map<Class<? extends WeaveLifecycleProvider>, Set<Class<? extends WeaveLifecycleProvider>>> result = + LazyMap.lazyMap( + new HashMap<Class<? extends WeaveLifecycleProvider>, Set<Class<? extends WeaveLifecycleProvider>>>(), + new Factory<Set<Class<? extends WeaveLifecycleProvider>>>() { + + @Override + public Set<Class<? extends WeaveLifecycleProvider>> create() { + return new HashSet<Class<? extends WeaveLifecycleProvider>>(); + } + }); + + for (WeaveLifecycleProvider<?> provider : providers) { + final Class<? extends WeaveLifecycleProvider> type = provider.getClass(); + Collections.addAll(result.get(type), consumedBy(type)); + + for (Class<? extends WeaveLifecycleProvider> dependent : producedBy(type)) { + result.get(dependent).add(type); + } + } + return result; + } + + /** + * Order providers. + * + * @param providers to sort + * @param order to respect + * @return reordered providers + */ + @SuppressWarnings("rawtypes") + private static <P extends WeaveLifecycleProvider> Iterable<P> imposeOrder(final Iterable<P> providers, + final Iterable<Class<? extends WeaveLifecycleProvider>> order) { + + final Set<P> result = new LinkedHashSet<P>(); + + for (Class<? extends WeaveLifecycleProvider> type : order) { + for (P provider : providers) { + if (type.isInstance(provider)) { + result.add(provider); + } + } + } + return Collections.unmodifiableSet(result); + } +} Propchange: commons/proper/weaver/trunk/processor/src/main/java/org/apache/commons/weaver/utils/Providers.java ------------------------------------------------------------------------------ svn:executable = * Added: commons/proper/weaver/trunk/processor/src/test/java/org/apache/commons/weaver/utils/ProvidersTest.java URL: http://svn.apache.org/viewvc/commons/proper/weaver/trunk/processor/src/test/java/org/apache/commons/weaver/utils/ProvidersTest.java?rev=1720392&view=auto ============================================================================== --- commons/proper/weaver/trunk/processor/src/test/java/org/apache/commons/weaver/utils/ProvidersTest.java (added) +++ commons/proper/weaver/trunk/processor/src/test/java/org/apache/commons/weaver/utils/ProvidersTest.java Wed Dec 16 17:15:51 2015 @@ -0,0 +1,93 @@ +/* + * 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. + */ +package org.apache.commons.weaver.utils; + +import static org.junit.Assert.assertThat; + +import java.util.Arrays; + +import org.apache.commons.weaver.Consumes; +import org.apache.commons.weaver.Produces; +import org.apache.commons.weaver.lifecycle.WeaveLifecycleToken; +import org.apache.commons.weaver.spi.WeaveLifecycleProvider; +import org.apache.commons.weaver.spi.Weaver; +import org.hamcrest.collection.IsIterableContainingInOrder; +import org.junit.Test; + +public class ProvidersTest { + + @Test(expected = NullPointerException.class) + public void testSortNull() { + Providers.sort(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testSortNullElement() { + Providers.sort(Arrays.asList((Weaver) null)); + } + + public interface FauxWeaveProvider extends WeaveLifecycleProvider<WeaveLifecycleToken.Weave> { + } + + public class A implements FauxWeaveProvider { + } + + @Consumes(A.class) + @Produces(C.class) + public class B implements FauxWeaveProvider { + } + + public class C implements FauxWeaveProvider { + } + + @Consumes(X.class) + public class W implements FauxWeaveProvider { + } + + @Consumes(Y.class) + public class X implements FauxWeaveProvider { + } + + public class Y implements FauxWeaveProvider { + } + + @Produces(Y.class) + public class Z implements FauxWeaveProvider { + } + + @Consumes(Y.class) + @Produces(Z.class) + public class Monkeywrench implements FauxWeaveProvider { + } + + private FauxWeaveProvider a = new A(), b = new B(), c = new C(), w = new W(), x = new X(), y = new Y(), z = new Z(), + monkeywrench = new Monkeywrench(); + + @Test + public void testSort() { + assertThat(Providers.sort(Arrays.asList(b, a, c)), IsIterableContainingInOrder.contains(a, b, c)); + assertThat(Providers.sort(Arrays.asList(y, w, x, z)), IsIterableContainingInOrder.contains(z, y, x, w)); + } + + @Test(expected = IllegalStateException.class) + public void testCircularSort() { + Providers.sort(Arrays.asList(y, z, monkeywrench)); + } + +} Propchange: commons/proper/weaver/trunk/processor/src/test/java/org/apache/commons/weaver/utils/ProvidersTest.java ------------------------------------------------------------------------------ svn:executable = *