From 42e2b371bc649cfa5c82fb248d5f6e7e8e18baec Mon Sep 17 00:00:00 2001 From: Henry Lee Date: Thu, 30 Nov 2023 20:22:57 +0900 Subject: [PATCH 1/3] refactor(java): maven-shared-io --- Java-base/maven-shared-io/Dockerfile | 28 + Java-base/maven-shared-io/src/Jenkinsfile | 20 + Java-base/maven-shared-io/src/README.md | 99 +++ Java-base/maven-shared-io/src/pom.xml | 123 ++++ .../io/download/DefaultDownloadManager.java | 213 ++++++ .../io/download/DownloadFailedException.java | 63 ++ .../shared/io/download/DownloadManager.java | 58 ++ .../shared/io/location/ArtifactLocation.java | 42 ++ .../io/location/ArtifactLocatorStrategy.java | 193 ++++++ .../ClasspathResourceLocatorStrategy.java | 83 +++ .../shared/io/location/FileLocation.java | 176 +++++ .../io/location/FileLocatorStrategy.java | 53 ++ .../maven/shared/io/location/Location.java | 76 +++ .../maven/shared/io/location/Locator.java | 117 ++++ .../shared/io/location/LocatorStrategy.java | 38 ++ .../maven/shared/io/location/URLLocation.java | 82 +++ .../io/location/URLLocatorStrategy.java | 80 +++ .../io/logging/DefaultMessageHolder.java | 616 ++++++++++++++++++ .../shared/io/logging/MessageHolder.java | 290 +++++++++ .../shared/io/logging/MessageLevels.java | 117 ++++ .../maven/shared/io/logging/MessageSink.java | 55 ++ .../maven/shared/io/logging/MojoLogSink.java | 73 +++ .../shared/io/logging/PlexusLoggerSink.java | 71 ++ .../AbstractResourceInclusionScanner.java | 95 +++ .../io/scan/InclusionScanException.java | 45 ++ .../io/scan/ResourceInclusionScanner.java | 46 ++ .../scan/SimpleResourceInclusionScanner.java | 64 ++ .../shared/io/scan/StaleResourceScanner.java | 123 ++++ .../io/scan/mapping/SingleTargetMapping.java | 63 ++ .../shared/io/scan/mapping/SourceMapping.java | 41 ++ .../shared/io/scan/mapping/SuffixMapping.java | 77 +++ .../resources/META-INF/plexus/components.xml | 33 + .../src/src/site/resources/download.cgi | 22 + .../maven-shared-io/src/src/site/site.xml | 37 ++ .../src/src/site/xdoc/download.xml.vm | 126 ++++ .../org/apache/maven/shared/io/Utils.java | 55 ++ .../download/DefaultDownloadManagerTest.java | 559 ++++++++++++++++ .../download/DownloadFailedExceptionTest.java | 44 ++ .../io/location/ArtifactLocationTest.java | 81 +++ .../location/ArtifactLocatorStrategyTest.java | 507 ++++++++++++++ .../ClasspathResourceLocatorStrategyTest.java | 59 ++ .../shared/io/location/FileLocationTest.java | 180 +++++ .../io/location/FileLocatorStrategyTest.java | 70 ++ .../maven/shared/io/location/LocatorTest.java | 138 ++++ .../shared/io/location/URLLocationTest.java | 81 +++ .../io/location/URLLocatorStrategyTest.java | 79 +++ .../io/logging/DefaultMessageHolderTest.java | 304 +++++++++ .../io/scan/mapping/SuffixMappingTest.java | 130 ++++ .../resources/META-INF/maven/test.properties | 17 + 49 files changed, 5842 insertions(+) create mode 100644 Java-base/maven-shared-io/Dockerfile create mode 100644 Java-base/maven-shared-io/src/Jenkinsfile create mode 100644 Java-base/maven-shared-io/src/README.md create mode 100644 Java-base/maven-shared-io/src/pom.xml create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/download/DefaultDownloadManager.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/download/DownloadFailedException.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/download/DownloadManager.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/ArtifactLocation.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/ArtifactLocatorStrategy.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/ClasspathResourceLocatorStrategy.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/FileLocation.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/FileLocatorStrategy.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/Location.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/Locator.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/LocatorStrategy.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/URLLocation.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/URLLocatorStrategy.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/DefaultMessageHolder.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/MessageHolder.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/MessageLevels.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/MessageSink.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/MojoLogSink.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/PlexusLoggerSink.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/AbstractResourceInclusionScanner.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/InclusionScanException.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/ResourceInclusionScanner.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/SimpleResourceInclusionScanner.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/StaleResourceScanner.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/mapping/SingleTargetMapping.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/mapping/SourceMapping.java create mode 100644 Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/mapping/SuffixMapping.java create mode 100644 Java-base/maven-shared-io/src/src/main/resources/META-INF/plexus/components.xml create mode 100644 Java-base/maven-shared-io/src/src/site/resources/download.cgi create mode 100644 Java-base/maven-shared-io/src/src/site/site.xml create mode 100644 Java-base/maven-shared-io/src/src/site/xdoc/download.xml.vm create mode 100644 Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/Utils.java create mode 100644 Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/download/DefaultDownloadManagerTest.java create mode 100644 Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/download/DownloadFailedExceptionTest.java create mode 100644 Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/ArtifactLocationTest.java create mode 100644 Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/ArtifactLocatorStrategyTest.java create mode 100644 Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/ClasspathResourceLocatorStrategyTest.java create mode 100644 Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/FileLocationTest.java create mode 100644 Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/FileLocatorStrategyTest.java create mode 100644 Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/LocatorTest.java create mode 100644 Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/URLLocationTest.java create mode 100644 Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/URLLocatorStrategyTest.java create mode 100644 Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/logging/DefaultMessageHolderTest.java create mode 100644 Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/scan/mapping/SuffixMappingTest.java create mode 100644 Java-base/maven-shared-io/src/src/test/resources/META-INF/maven/test.properties diff --git a/Java-base/maven-shared-io/Dockerfile b/Java-base/maven-shared-io/Dockerfile new file mode 100644 index 000000000..e208c4890 --- /dev/null +++ b/Java-base/maven-shared-io/Dockerfile @@ -0,0 +1,28 @@ +FROM ubuntu:22.04 + +RUN export DEBIAN_FRONTEND=noninteractive \ + && apt-get update \ + && apt-get install -y software-properties-common \ + && add-apt-repository ppa:deadsnakes/ppa \ + && apt-get update \ + && apt-get install -y \ + build-essential \ + git \ + vim \ + jq \ + && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/list/* + +RUN apt-get -y install sudo \ + openjdk-8-jdk \ + maven + +RUN bash -c "echo 2 | update-alternatives --config java" + +COPY src /workspace +WORKDIR /workspace + +RUN mvn install -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false + +RUN mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 + +ENV TZ=Asia/Seoul diff --git a/Java-base/maven-shared-io/src/Jenkinsfile b/Java-base/maven-shared-io/src/Jenkinsfile new file mode 100644 index 000000000..09ac70f12 --- /dev/null +++ b/Java-base/maven-shared-io/src/Jenkinsfile @@ -0,0 +1,20 @@ +/** + * 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. + */ + +asfMavenTlpStdBuild() diff --git a/Java-base/maven-shared-io/src/README.md b/Java-base/maven-shared-io/src/README.md new file mode 100644 index 000000000..cc76fa9f2 --- /dev/null +++ b/Java-base/maven-shared-io/src/README.md @@ -0,0 +1,99 @@ + +Contributing to [Apache Maven Shared IO](https://maven.apache.org/shared/maven-shared-io/) +====================== + +[![ASF Jira](https://img.shields.io/endpoint?url=https%3A%2F%2Fmaven.apache.org%2Fbadges%2Fasf_jira-MSHARED.json)][jira] +[![Apache License, Version 2.0, January 2004](https://img.shields.io/github/license/apache/maven.svg?label=License)][license] +[![Maven Central](https://img.shields.io/maven-central/v/org.apache.maven.shared/maven-shared-io.svg?label=Maven%20Central)](https://search.maven.org/artifact/org.apache.maven.shared/maven-shared-io) +[![Jenkins Status](https://img.shields.io/jenkins/s/https/builds.apache.org/job/maven-box/job/maven-shared-io/job/master.svg)][build] +[![Jenkins tests](https://img.shields.io/jenkins/t/https/builds.apache.org/job/maven-box/job/maven-shared-io/job/master.svg)][test-results] + + +You have found a bug or you have an idea for a cool new feature? Contributing +code is a great way to give something back to the open source community. Before +you dig right into the code, there are a few guidelines that we need +contributors to follow so that we can have a chance of keeping on top of +things. + +Getting Started +--------------- + ++ Make sure you have a [JIRA account](https://issues.apache.org/jira/). ++ Make sure you have a [GitHub account](https://github.com/signup/free). ++ If you're planning to implement a new feature, it makes sense to discuss your changes + on the [dev list][ml-list] first. + This way you can make sure you're not wasting your time on something that isn't + considered to be in Apache Maven's scope. ++ Submit a ticket for your issue, assuming one does not already exist. + + Clearly describe the issue, including steps to reproduce when it is a bug. + + Make sure you fill in the earliest version that you know has the issue. ++ Fork the repository on GitHub. + +Making and Submitting Changes +-------------- + +We accept Pull Requests via GitHub. The [developer mailing list][ml-list] is the +main channel of communication for contributors. +There are some guidelines which will make applying PRs easier for us: ++ Create a topic branch from where you want to base your work (this is usually the master branch). + Push your changes to a topic branch in your fork of the repository. ++ Make commits of logical units. ++ Respect the original code style: by using the same [codestyle][code-style], + patches should only highlight the actual difference, not being disturbed by any formatting issues: + + Only use spaces for indentation. + + Create minimal diffs - disable on save actions like reformat source code or organize imports. + If you feel the source code should be reformatted, create a separate PR for this change. + + Check for unnecessary whitespace with `git diff --check` before committing. ++ Make sure your commit messages are in the proper format. Your commit message should contain the key of the JIRA issue. +``` +[MSHARED-XXX] - Subject of the JIRA Ticket + Optional supplemental description. +``` ++ Make sure you have added the necessary tests (JUnit/IT) for your changes. ++ Run all the tests with `mvn -Prun-its verify` to assure nothing else was accidentally broken. ++ Submit a pull request to the repository in the Apache organization. ++ Update your JIRA ticket and include a link to the pull request in the ticket. + +If you plan to contribute on a regular basis, please consider filing a [contributor license agreement][cla]. + +Making Trivial Changes +---------------------- + +For changes of a trivial nature to comments and documentation, it is not always +necessary to create a new ticket in JIRA. In this case, it is appropriate to +start the first line of a commit with '(doc)' instead of a ticket number. + +Additional Resources +-------------------- + ++ [Contributing patches](https://maven.apache.org/guides/development/guide-maven-development.html#Creating_and_submitting_a_patch) ++ [Apache Maven Shared Components project page][jira] ++ [Contributor License Agreement][cla] ++ [General GitHub documentation](https://help.github.com/) ++ [GitHub pull request documentation](https://help.github.com/send-pull-requests/) ++ [Apache Maven Twitter Account](https://twitter.com/ASFMavenProject) ++ #Maven IRC channel on freenode.org + +[jira]: https://issues.apache.org/jira/projects/MSHARED/ +[license]: https://www.apache.org/licenses/LICENSE-2.0 +[ml-list]: https://maven.apache.org/mailing-lists.html +[code-style]: https://maven.apache.org/developers/conventions/code.html +[cla]: https://www.apache.org/licenses/#clas +[maven-wiki]: https://cwiki.apache.org/confluence/display/MAVEN/Index +[test-results]: https://builds.apache.org/job/maven-box/job/maven-shared-io/job/master/lastCompletedBuild/testReport/ +[build]: https://builds.apache.org/job/maven-box/job/maven-shared-io/job/master/ diff --git a/Java-base/maven-shared-io/src/pom.xml b/Java-base/maven-shared-io/src/pom.xml new file mode 100644 index 000000000..5e5ab5db9 --- /dev/null +++ b/Java-base/maven-shared-io/src/pom.xml @@ -0,0 +1,123 @@ + + + + 4.0.0 + + + org.apache.maven.shared + maven-shared-components + 34 + ../../pom/maven/maven-shared-components/pom.xml + + + maven-shared-io + 3.0.1-SNAPSHOT + + Apache Maven Shared I/O API + API for I/O support like logging, download or file scanning. + + + + Joakim Erdfelt + joakim@erdfelt.com + + + + + scm:git:https://gitbox.apache.org/repos/asf/maven-shared-io.git + scm:git:https://gitbox.apache.org/repos/asf/maven-shared-io.git + https://github.com/apache/maven-shared-io/tree/${project.scm.tag} + HEAD + + + jira + https://issues.apache.org/jira/browse/MSHARED/component/12326440 + + + Jenkins + https://builds.apache.org/job/maven-box/job/maven-shared-io/ + + + + apache.website + scm:svn:https://svn.apache.org/repos/asf/maven/website/components/${maven.site.path} + + + + + 3.0 + 7 + RedundantThrows,NewlineAtEndOfFile,ParameterNumber,MethodLength,FileLength,JavadocType + 2020-04-04T09:03:59Z + + + + + + org.apache.maven + maven-core + ${mavenVersion} + + + org.apache.maven + maven-artifact + ${mavenVersion} + + + org.apache.maven + maven-compat + ${mavenVersion} + + + org.apache.maven.wagon + wagon-provider-api + 3.0.0 + + + org.apache.maven + maven-plugin-api + ${mavenVersion} + + + org.apache.maven.shared + maven-shared-utils + 3.2.1 + + + org.sonatype.sisu + sisu-inject-plexus + 1.4.2 + + + + org.easymock + easymock + 3.2 + test + + + junit + junit + 4.13 + test + + + + diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/download/DefaultDownloadManager.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/download/DefaultDownloadManager.java new file mode 100644 index 000000000..5cf008720 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/download/DefaultDownloadManager.java @@ -0,0 +1,213 @@ +package org.apache.maven.shared.io.download; + +/* + * 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. + */ + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.maven.artifact.manager.WagonManager; +import org.apache.maven.shared.io.logging.MessageHolder; +import org.apache.maven.wagon.ConnectionException; +import org.apache.maven.wagon.ResourceDoesNotExistException; +import org.apache.maven.wagon.TransferFailedException; +import org.apache.maven.wagon.UnsupportedProtocolException; +import org.apache.maven.wagon.Wagon; +import org.apache.maven.wagon.authentication.AuthenticationException; +import org.apache.maven.wagon.authorization.AuthorizationException; +import org.apache.maven.wagon.events.TransferListener; +import org.apache.maven.wagon.repository.Repository; + +/** + * The Implementation of the {@link DownloadManager} + * + */ +public class DefaultDownloadManager + implements DownloadManager +{ + + /** + * Role hint. + */ + public static final String ROLE_HINT = "default"; + + private WagonManager wagonManager; + + private Map cache = new HashMap(); + + /** + * Create an instance of the {@code DefaultDownloadManager}. + */ + public DefaultDownloadManager() + { + } + + /** + * @param wagonManager {@link org.apache.maven.repository.legacy.WagonManager} + */ + public DefaultDownloadManager( WagonManager wagonManager ) + { + this.wagonManager = wagonManager; + } + + /** {@inheritDoc} */ + public File download( String url, MessageHolder messageHolder ) + throws DownloadFailedException + { + return download( url, Collections.emptyList(), messageHolder ); + } + + /** {@inheritDoc} */ + public File download( String url, List transferListeners, MessageHolder messageHolder ) + throws DownloadFailedException + { + File downloaded = (File) cache.get( url ); + + if ( downloaded != null && downloaded.exists() ) + { + messageHolder.addMessage( "Using cached download: " + downloaded.getAbsolutePath() ); + + return downloaded; + } + + URL sourceUrl; + try + { + sourceUrl = new URL( url ); + } + catch ( MalformedURLException e ) + { + throw new DownloadFailedException( url, "Download failed due to invalid URL. Reason: " + e.getMessage(), + e ); + } + + Wagon wagon = null; + + // Retrieve the correct Wagon instance used to download the remote archive + try + { + wagon = wagonManager.getWagon( sourceUrl.getProtocol() ); + } + catch ( UnsupportedProtocolException e ) + { + throw new DownloadFailedException( url, "Download failed. Reason: " + e.getMessage(), e ); + } + + messageHolder.addMessage( "Using wagon: " + wagon + " to download: " + url ); + + try + { + // create the landing file in /tmp for the downloaded source archive + downloaded = File.createTempFile( "download-", null ); + + // delete when the JVM exits, to avoid polluting the temp dir... + downloaded.deleteOnExit(); + } + catch ( IOException e ) + { + throw new DownloadFailedException( url, "Failed to create temporary file target for download. Reason: " + + e.getMessage(), e ); + } + + messageHolder.addMessage( "Download target is: " + downloaded.getAbsolutePath() ); + + // split the download URL into base URL and remote path for connecting, then retrieving. + String remotePath = sourceUrl.getPath(); + String baseUrl = url.substring( 0, url.length() - remotePath.length() ); + + for ( Iterator it = transferListeners.iterator(); it.hasNext(); ) + { + wagon.addTransferListener( it.next() ); + } + + // connect to the remote site, and retrieve the archive. Note the separate methods in which + // base URL and remote path are used. + Repository repo = new Repository( sourceUrl.getHost(), baseUrl ); + + messageHolder.addMessage( "Connecting to: " + repo.getHost() + "(baseUrl: " + repo.getUrl() + ")" ); + + try + { + wagon.connect( repo, wagonManager.getAuthenticationInfo( repo.getId() ), + wagonManager.getProxy( sourceUrl.getProtocol() ) ); + } + catch ( ConnectionException e ) + { + throw new DownloadFailedException( url, "Download failed. Reason: " + e.getMessage(), e ); + } + catch ( AuthenticationException e ) + { + throw new DownloadFailedException( url, "Download failed. Reason: " + e.getMessage(), e ); + } + + messageHolder.addMessage( "Getting: " + remotePath ); + + try + { + wagon.get( remotePath, downloaded ); + + // cache this for later download requests to the same instance... + cache.put( url, downloaded ); + + return downloaded; + } + catch ( TransferFailedException e ) + { + throw new DownloadFailedException( url, "Download failed. Reason: " + e.getMessage(), e ); + } + catch ( ResourceDoesNotExistException e ) + { + throw new DownloadFailedException( url, "Download failed. Reason: " + e.getMessage(), e ); + } + catch ( AuthorizationException e ) + { + throw new DownloadFailedException( url, "Download failed. Reason: " + e.getMessage(), e ); + } + finally + { + // ensure the Wagon instance is closed out properly. + if ( wagon != null ) + { + try + { + messageHolder.addMessage( "Disconnecting." ); + + wagon.disconnect(); + } + catch ( ConnectionException e ) + { + messageHolder.addMessage( "Failed to disconnect wagon for: " + url, e ); + } + + for ( Iterator it = transferListeners.iterator(); it.hasNext(); ) + { + wagon.removeTransferListener( it.next() ); + } + } + } + } + +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/download/DownloadFailedException.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/download/DownloadFailedException.java new file mode 100644 index 000000000..669ce8bca --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/download/DownloadFailedException.java @@ -0,0 +1,63 @@ +package org.apache.maven.shared.io.download; + +/* + * 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. + */ + +/** + * The Download Failed Exception. + * + */ +public class DownloadFailedException + extends Exception +{ + + private static final long serialVersionUID = 1L; + + private String url; + + /** + * @param url The url. + * @param message The message. + * @param cause The cause of the problem. + */ + public DownloadFailedException( String url, String message, Throwable cause ) + { + super( message, cause ); + this.url = url; + } + + /** + * @param url The url. + * @param message The message. + */ + public DownloadFailedException( String url, String message ) + { + super( message ); + this.url = url; + } + + /** + * @return The url. + */ + public String getUrl() + { + return url; + } + +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/download/DownloadManager.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/download/DownloadManager.java new file mode 100644 index 000000000..6d2e91a81 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/download/DownloadManager.java @@ -0,0 +1,58 @@ +package org.apache.maven.shared.io.download; + +/* + * 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. + */ + +import java.io.File; +import java.util.List; + +import org.apache.maven.shared.io.logging.MessageHolder; +import org.apache.maven.wagon.events.TransferListener; + +/** + * The Download Manager interface. + * + */ +public interface DownloadManager +{ + /** + * The Role. + */ + String ROLE = DownloadManager.class.getName(); + + /** + * @param url The URL. + * @param messageHolder {@link MessageHolder} + * @return {@link File} + * @throws DownloadFailedException in case of exception. + */ + File download( String url, MessageHolder messageHolder ) + throws DownloadFailedException; + + /** + * @param url The URL. + * @param transferListeners {@link TransferListener} + * @param messageHolder {@link MessageHolder} + * @return {@link File} + * @throws DownloadFailedException in case of exception. + */ + File download( String url, List transferListeners, MessageHolder messageHolder ) + throws DownloadFailedException; + +} \ No newline at end of file diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/ArtifactLocation.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/ArtifactLocation.java new file mode 100644 index 000000000..dea6e68b6 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/ArtifactLocation.java @@ -0,0 +1,42 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import org.apache.maven.artifact.Artifact; + +/** + * The artifact location. + * + */ +public class ArtifactLocation + extends FileLocation +{ + + /** + * @param artifact {@link Artifact} + * @param specification The specification. + */ + public ArtifactLocation( Artifact artifact, String specification ) + { + super( specification ); + setFile( artifact.getFile() ); + } + +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/ArtifactLocatorStrategy.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/ArtifactLocatorStrategy.java new file mode 100644 index 000000000..634b37105 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/ArtifactLocatorStrategy.java @@ -0,0 +1,193 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import java.util.List; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.resolver.ArtifactNotFoundException; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; +import org.apache.maven.artifact.resolver.ArtifactResolver; +import org.apache.maven.shared.io.logging.MessageHolder; + +/** + * The locator strategy. + * + */ +public class ArtifactLocatorStrategy + implements LocatorStrategy +{ + private final ArtifactFactory factory; + + private final ArtifactResolver resolver; + + private String defaultArtifactType = "jar"; + + private final ArtifactRepository localRepository; + + private final List remoteRepositories; + + private String defaultClassifier = null; + + /** + * @param factory {@link ArtifactFactory} + * @param resolver {@link ArtifactResolver} + * @param localRepository {@link ArtifactRepository} + * @param remoteRepositories {@link ArtifactRepository} + */ + public ArtifactLocatorStrategy( ArtifactFactory factory, ArtifactResolver resolver, + ArtifactRepository localRepository, List remoteRepositories ) + { + this.factory = factory; + this.resolver = resolver; + this.localRepository = localRepository; + this.remoteRepositories = remoteRepositories; + } + + /** + * @param factory {@link ArtifactFactory} + * @param resolver {@link ArtifactResolver} + * @param localRepository {@link ArtifactRepository} + * @param remoteRepositories {@link ArtifactRepository} + * @param defaultArtifactType default artifact type. + */ + public ArtifactLocatorStrategy( ArtifactFactory factory, ArtifactResolver resolver, + ArtifactRepository localRepository, List remoteRepositories, + String defaultArtifactType ) + { + this.factory = factory; + this.resolver = resolver; + this.localRepository = localRepository; + this.remoteRepositories = remoteRepositories; + this.defaultArtifactType = defaultArtifactType; + } + + /** + * @param factory {@link ArtifactFactory} + * @param resolver {@link ArtifactResolver} + * @param localRepository {@link ArtifactRepository} + * @param remoteRepositories {@link ArtifactRepository} + * @param defaultArtifactType default artifact type. + * @param defaultClassifier default classifier. + */ + public ArtifactLocatorStrategy( ArtifactFactory factory, ArtifactResolver resolver, + ArtifactRepository localRepository, List remoteRepositories, + String defaultArtifactType, String defaultClassifier ) + { + this.factory = factory; + this.resolver = resolver; + this.localRepository = localRepository; + this.remoteRepositories = remoteRepositories; + this.defaultArtifactType = defaultArtifactType; + this.defaultClassifier = defaultClassifier; + } + + /** + * Assumes artifact identity is given in a set of comma-delimited tokens of + * the form: groupId:artifactId:version:type:classifier, where + * type and classifier are optional. + * @param locationSpecification location spec. + * @param messageHolder {@link MessageHolder} + * @return location. + */ + public Location resolve( String locationSpecification, MessageHolder messageHolder ) + { + String[] parts = locationSpecification.split( ":" ); + + Location location = null; + + if ( parts.length > 2 ) + { + String groupId = parts[0]; + String artifactId = parts[1]; + String version = parts[2]; + + String type = defaultArtifactType; + if ( parts.length > 3 ) + { + if ( parts[3].trim().length() > 0 ) + { + type = parts[3]; + } + } + + String classifier = defaultClassifier; + if ( parts.length > 4 ) + { + classifier = parts[4]; + } + + if ( parts.length > 5 ) + { + messageHolder.newMessage().append( "Location specification has unused tokens: \'" ); + + for ( int i = 5; i < parts.length; i++ ) + { + messageHolder.append( ":" + parts[i] ); + } + } + + Artifact artifact; + if ( classifier == null ) + { + artifact = factory.createArtifact( groupId, artifactId, version, null, type ); + } + else + { + artifact = factory.createArtifactWithClassifier( groupId, artifactId, version, type, classifier ); + } + + try + { + resolver.resolve( artifact, remoteRepositories, localRepository ); + + if ( artifact.getFile() != null ) + { + location = new ArtifactLocation( artifact, locationSpecification ); + } + else + { + messageHolder.addMessage( "Supposedly resolved artifact: " + artifact.getId() + + " does not have an associated file." ); + } + } + catch ( ArtifactResolutionException e ) + { + messageHolder.addMessage( "Failed to resolve artifact: " + artifact.getId() + " for location: " + + locationSpecification, e ); + } + catch ( ArtifactNotFoundException e ) + { + messageHolder.addMessage( "Failed to resolve artifact: " + artifact.getId() + " for location: " + + locationSpecification, e ); + } + } + else + { + messageHolder.addMessage( "Invalid artifact specification: \'" + locationSpecification + + "\'. Must contain at least three fields, separated by ':'." ); + } + + return location; + } + +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/ClasspathResourceLocatorStrategy.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/ClasspathResourceLocatorStrategy.java new file mode 100644 index 000000000..4d850cfa6 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/ClasspathResourceLocatorStrategy.java @@ -0,0 +1,83 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import java.net.URL; + +import org.apache.maven.shared.io.logging.MessageHolder; + +/** + * classpath resource locator strategy. + * + */ +public class ClasspathResourceLocatorStrategy + implements LocatorStrategy +{ + + private String tempFilePrefix = "location."; + + private String tempFileSuffix = ".cpurl"; + + private boolean tempFileDeleteOnExit = true; + + /** + * Create instance. + */ + public ClasspathResourceLocatorStrategy() + { + } + + /** + * @param tempFilePrefix Prefix. + * @param tempFileSuffix Suffix. + * @param tempFileDeleteOnExit delete on exit. + */ + public ClasspathResourceLocatorStrategy( String tempFilePrefix, String tempFileSuffix, + boolean tempFileDeleteOnExit ) + { + this.tempFilePrefix = tempFilePrefix; + this.tempFileSuffix = tempFileSuffix; + this.tempFileDeleteOnExit = tempFileDeleteOnExit; + } + + /** {@inheritDoc} */ + public Location resolve( String locationSpecification, MessageHolder messageHolder ) + { + ClassLoader cloader = Thread.currentThread().getContextClassLoader(); + + URL resource = cloader.getResource( locationSpecification ); + + Location location = null; + + if ( resource != null ) + { + location = new URLLocation( resource, locationSpecification, tempFilePrefix, tempFileSuffix, + tempFileDeleteOnExit ); + } + else + { + messageHolder.addMessage( "Failed to resolve classpath resource: " + locationSpecification + + " from classloader: " + cloader ); + } + + return location; + } + +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/FileLocation.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/FileLocation.java new file mode 100644 index 000000000..a8a62e3ec --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/FileLocation.java @@ -0,0 +1,176 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; + + +/** + * file location implementation. + * + */ +public class FileLocation + implements Location +{ + + private File file; + private FileChannel channel; + private final String specification; + private FileInputStream stream; + + /** + * @param file {@link File} + * @param specification spec. + */ + public FileLocation( File file, String specification ) + { + this.file = file; + this.specification = specification; + } + + /** + * @param specification spec. + */ + protected FileLocation( String specification ) + { + this.specification = specification; + } + + /** {@inheritDoc} */ + public void close() + { + if ( ( channel != null ) && channel.isOpen() ) + { + try + { + channel.close(); + } + catch ( IOException e ) + { + //swallow it. + } + } + + if ( stream != null ) + { + try + { + stream.close(); + } + catch ( IOException e ) + { + // swallow it. + } + } + } + + /** {@inheritDoc} */ + public File getFile() + throws IOException + { + initFile(); + + return unsafeGetFile(); + } + + /** + * @return {@link File} + */ + protected File unsafeGetFile() + { + return file; + } + + /** + * initialize file. + * @throws IOException in case error. + */ + protected void initFile() + throws IOException + { + // TODO: Log this in the debug log-level... + if ( file == null ) + { + file = new File( specification ); + } + } + + /** + * @param file {@link File} + */ + protected void setFile( File file ) + { + if ( channel != null ) + { + throw new IllegalStateException( "Location is already open; cannot setFile(..)." ); + } + + this.file = file; + } + + /** {@inheritDoc} */ + public String getSpecification() + { + return specification; + } + + /** {@inheritDoc} */ + public void open() + throws IOException + { + if ( stream == null ) + { + initFile(); + + stream = new FileInputStream( file ); + channel = stream.getChannel(); + } + } + + /** {@inheritDoc} */ + public int read( ByteBuffer buffer ) + throws IOException + { + open(); + return channel.read( buffer ); + } + + /** {@inheritDoc} */ + public int read( byte[] buffer ) + throws IOException + { + open(); + return channel.read( ByteBuffer.wrap( buffer ) ); + } + + /** {@inheritDoc} */ + public InputStream getInputStream() + throws IOException + { + open(); + return stream; + } + +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/FileLocatorStrategy.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/FileLocatorStrategy.java new file mode 100644 index 000000000..92aa3dd38 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/FileLocatorStrategy.java @@ -0,0 +1,53 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import java.io.File; + +import org.apache.maven.shared.io.logging.MessageHolder; + +/** + * file locator strategy. + * + */ +public class FileLocatorStrategy + implements LocatorStrategy +{ + + /** {@inheritDoc} */ + public Location resolve( String locationSpecification, MessageHolder messageHolder ) + { + File file = new File( locationSpecification ); + + Location location = null; + + if ( file.exists() ) + { + location = new FileLocation( file, locationSpecification ); + } + else + { + messageHolder.addMessage( "File: " + file.getAbsolutePath() + " does not exist." ); + } + + return location; + } + +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/Location.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/Location.java new file mode 100644 index 000000000..cfbd4ae4a --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/Location.java @@ -0,0 +1,76 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; + +/** + * The location interface. + * + */ +public interface Location +{ + + /** + * @return {@link File}. + * @throws IOException in case of an error. + */ + File getFile() throws IOException; + + /** + * open the location. + * @throws IOException in case of an error. + */ + void open() throws IOException; + + /** + * Close the location. + */ + void close(); + + /** + * @param buffer The buffer. + * @return number of read bytes. + * @throws IOException in case of an error. + */ + int read( ByteBuffer buffer ) throws IOException; + + /** + * @param buffer The buffer. + * @return number of read bytes. + * @throws IOException in case of an error. + */ + int read( byte[] buffer ) throws IOException; + + /** + * @return the resulting input stream. + * @throws IOException in case of an error. + */ + InputStream getInputStream() throws IOException; + + /** + * @return spec. + */ + String getSpecification(); + +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/Locator.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/Locator.java new file mode 100644 index 000000000..45f27aff5 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/Locator.java @@ -0,0 +1,117 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.maven.shared.io.logging.DefaultMessageHolder; +import org.apache.maven.shared.io.logging.MessageHolder; + +/** + * The Locator. + * + */ +public final class Locator +{ + + private List strategies; + private final MessageHolder messageHolder; + + /** + * @param strategies List of strategies. + * @param messageHolder {@link MessageHolder} + */ + public Locator( List strategies, MessageHolder messageHolder ) + { + this.messageHolder = messageHolder; + this.strategies = new ArrayList( strategies ); + } + + /** + * Create instance. + */ + public Locator() + { + this.messageHolder = new DefaultMessageHolder(); + this.strategies = new ArrayList(); + } + + /** + * @return {@link MessageHolder} + */ + public MessageHolder getMessageHolder() + { + return messageHolder; + } + + /** + * @param strategy The strategy to be added. + */ + public void addStrategy( LocatorStrategy strategy ) + { + this.strategies.add( strategy ); + } + + /** + * @param strategy the strategy to remove. + */ + public void removeStrategy( LocatorStrategy strategy ) + { + this.strategies.remove( strategy ); + } + + /** + * @param strategies the strategies to be set. + */ + public void setStrategies( List strategies ) + { + this.strategies.clear(); + this.strategies.addAll( strategies ); + } + + /** + * @return list of strategies. + */ + public List getStrategies() + { + return strategies; + } + + /** + * @param locationSpecification location spec. + * @return {@link Location} + */ + public Location resolve( String locationSpecification ) + { + Location location = null; + + for ( Iterator it = strategies.iterator(); location == null && it.hasNext(); ) + { + LocatorStrategy strategy = (LocatorStrategy) it.next(); + + location = strategy.resolve( locationSpecification, messageHolder ); + } + + return location; + } + +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/LocatorStrategy.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/LocatorStrategy.java new file mode 100644 index 000000000..03e9d23cd --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/LocatorStrategy.java @@ -0,0 +1,38 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import org.apache.maven.shared.io.logging.MessageHolder; + +/** + * Locator Strategy interface. + * + */ +public interface LocatorStrategy +{ + + /** + * @param locationSpecification the specification. + * @param messageHolder {@link MessageHolder} + * @return {@link Location} + */ + Location resolve( String locationSpecification, MessageHolder messageHolder ); + +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/URLLocation.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/URLLocation.java new file mode 100644 index 000000000..cca1f24b7 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/URLLocation.java @@ -0,0 +1,82 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import java.io.File; +import java.io.IOException; +import java.net.URL; + +import org.apache.maven.shared.utils.io.FileUtils; + +/** + * The URL Location. + * + */ +public class URLLocation + extends FileLocation +{ + + private final URL url; + + private final String tempFilePrefix; + + private final String tempFileSuffix; + + private final boolean tempFileDeleteOnExit; + + /** + * @param url The URL. + * @param specification The spec. + * @param tempFilePrefix the prefix. + * @param tempFileSuffix The suffix. + * @param tempFileDeleteOnExit delete on exit. + */ + public URLLocation( URL url, String specification, String tempFilePrefix, String tempFileSuffix, + boolean tempFileDeleteOnExit ) + { + super( specification ); + + this.url = url; + this.tempFilePrefix = tempFilePrefix; + this.tempFileSuffix = tempFileSuffix; + this.tempFileDeleteOnExit = tempFileDeleteOnExit; + } + + /** {@inheritDoc} */ + protected void initFile() + throws IOException + { + // TODO: Log this in the debug log-level... + if ( unsafeGetFile() == null ) + { + File tempFile = File.createTempFile( tempFilePrefix, tempFileSuffix ); + + if ( tempFileDeleteOnExit ) + { + tempFile.deleteOnExit(); + } + + FileUtils.copyURLToFile( url, tempFile ); + + setFile( tempFile ); + } + } + +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/URLLocatorStrategy.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/URLLocatorStrategy.java new file mode 100644 index 000000000..e7d259d09 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/location/URLLocatorStrategy.java @@ -0,0 +1,80 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import java.net.MalformedURLException; +import java.net.URL; + +import org.apache.maven.shared.io.logging.MessageHolder; + +/** + * URL Locator Strategy. + * + */ +public class URLLocatorStrategy + implements LocatorStrategy +{ + + private String tempFilePrefix = "location."; + + private String tempFileSuffix = ".url"; + + private boolean tempFileDeleteOnExit = true; + + /** + * Create instance. + */ + public URLLocatorStrategy() + { + } + + /** + * @param tempFilePrefix prefix. + * @param tempFileSuffix suffix. + * @param tempFileDeleteOnExit delete on exit. + */ + public URLLocatorStrategy( String tempFilePrefix, String tempFileSuffix, boolean tempFileDeleteOnExit ) + { + this.tempFilePrefix = tempFilePrefix; + this.tempFileSuffix = tempFileSuffix; + this.tempFileDeleteOnExit = tempFileDeleteOnExit; + } + + /** {@inheritDoc} */ + public Location resolve( String locationSpecification, MessageHolder messageHolder ) + { + Location location = null; + + try + { + URL url = new URL( locationSpecification ); + + location = new URLLocation( url, locationSpecification, tempFilePrefix, tempFileSuffix, + tempFileDeleteOnExit ); + } + catch ( MalformedURLException e ) + { + messageHolder.addMessage( "Building URL from location: " + locationSpecification, e ); + } + + return location; + } + +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/DefaultMessageHolder.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/DefaultMessageHolder.java new file mode 100644 index 000000000..97eeb065f --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/DefaultMessageHolder.java @@ -0,0 +1,616 @@ +package org.apache.maven.shared.io.logging; + +/* + * 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. + */ + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Default Message Holder. + * + */ +public class DefaultMessageHolder + implements MessageHolder +{ + + private List messages = new ArrayList(); + + private Message currentMessage; + + private int defaultMessageLevel = MessageLevels.LEVEL_INFO; + + private boolean[] messageLevelStates; + + private MessageSink onDemandSink; + + /** + * Create instance. + */ + public DefaultMessageHolder() + { + this.messageLevelStates = MessageLevels.getLevelStates( MessageLevels.LEVEL_INFO ); + } + + /** + * @param maxMessageLevel max message level. + * @param defaultMessageLevel default message level. + */ + public DefaultMessageHolder( int maxMessageLevel, int defaultMessageLevel ) + { + this.defaultMessageLevel = defaultMessageLevel; + this.messageLevelStates = MessageLevels.getLevelStates( maxMessageLevel ); + } + + /** + * @param maxMessageLevel max message level. + * @param defaultMessageLevel default message level. + * @param onDemandSink {@link MessageSink} + */ + public DefaultMessageHolder( int maxMessageLevel, int defaultMessageLevel, MessageSink onDemandSink ) + { + this.defaultMessageLevel = defaultMessageLevel; + this.onDemandSink = onDemandSink; + this.messageLevelStates = MessageLevels.getLevelStates( maxMessageLevel ); + } + + /** {@inheritDoc} */ + public MessageHolder addMessage( CharSequence messagePart, Throwable error ) + { + return addMessage( defaultMessageLevel, messagePart, error ); + } + + /** + * @param level Level. + * @param messagePart Message part. + * @param error {@link Throwable} + * @return {@link MessageHolder} + */ + protected MessageHolder addMessage( int level, CharSequence messagePart, Throwable error ) + { + newMessage( level ); + append( messagePart.toString() ); + append( error ); + + return this; + } + + /** {@inheritDoc} */ + public MessageHolder addMessage( CharSequence messagePart ) + { + return addMessage( defaultMessageLevel, messagePart ); + } + + /** + * @param level level. + * @param messagePart message part. + * @return {@link MessageHolder} + */ + protected MessageHolder addMessage( int level, CharSequence messagePart ) + { + newMessage( level ); + append( messagePart.toString() ); + + return this; + } + + /** {@inheritDoc} */ + public MessageHolder addMessage( Throwable error ) + { + return addMessage( defaultMessageLevel, error ); + } + + /** + * @param level level. + * @param error {@link Throwable} + * @return {@link MessageHolder} + */ + protected MessageHolder addMessage( int level, Throwable error ) + { + newMessage( level ); + append( error ); + + return this; + } + + /** {@inheritDoc} */ + public MessageHolder append( CharSequence messagePart ) + { + if ( currentMessage == null ) + { + newMessage(); + } + + currentMessage.append( messagePart.toString() ); + + return this; + } + + /** {@inheritDoc} */ + public MessageHolder append( Throwable error ) + { + if ( currentMessage == null ) + { + newMessage(); + } + + currentMessage.setError( error ); + + return this; + } + + /** {@inheritDoc} */ + public boolean isEmpty() + { + return messages.isEmpty(); + } + + /** {@inheritDoc} */ + public MessageHolder newMessage() + { + newMessage( defaultMessageLevel ); + + return this; + } + + /** + * @param messageLevel message level. + */ + protected void newMessage( int messageLevel ) + { + if ( onDemandSink != null && currentMessage != null ) + { + renderTo( currentMessage, onDemandSink ); + } + + currentMessage = new Message( messageLevel, onDemandSink ); + messages.add( currentMessage ); + } + + /** {@inheritDoc} */ + public String render() + { + StringBuffer buffer = new StringBuffer(); + + int counter = 1; + for ( Iterator it = messages.iterator(); it.hasNext(); ) + { + Message message = (Message) it.next(); + + int ml = message.getMessageLevel(); + + if ( ml >= messageLevelStates.length || ml < 0 ) + { + ml = MessageLevels.LEVEL_DEBUG; + } + + if ( !messageLevelStates[ml] ) + { + continue; + } + + CharSequence content = message.render(); + String label = MessageLevels.getLevelLabel( message.getMessageLevel() ); + + if ( content.length() > label.length() + 3 ) + { + buffer.append( '[' ).append( counter++ ).append( "] " ); + buffer.append( content.toString() ); + + if ( it.hasNext() ) + { + buffer.append( "\n\n" ); + } + } + } + + return buffer.toString(); + } + + /** {@inheritDoc} */ + public int size() + { + return messages.size(); + } + + private static final class Message + { + private StringBuffer message = new StringBuffer(); + + private Throwable error; + + private final int messageLevel; + + private final MessageSink onDemandSink; + + Message( int messageLevel, MessageSink onDemandSink ) + { + this.messageLevel = messageLevel; + + this.onDemandSink = onDemandSink; + } + + public Message setError( Throwable pError ) + { + this.error = pError; + return this; + } + + public Message append( CharSequence pMessage ) + { + this.message.append( pMessage.toString() ); + return this; + } + + /** + * @return message level. + */ + public int getMessageLevel() + { + return messageLevel; + } + + /** + * @return Sequence. + */ + public CharSequence render() + { + StringBuffer buffer = new StringBuffer(); + + if ( onDemandSink == null ) + { + buffer.append( '[' ).append( MessageLevels.getLevelLabel( messageLevel ) ).append( "] " ); + } + if ( message != null && message.length() > 0 ) + { + buffer.append( message ); + + if ( error != null ) + { + buffer.append( '\n' ); + } + } + + if ( error != null ) + { + buffer.append( "Error:\n" ); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter( sw ); + error.printStackTrace( pw ); + + buffer.append( sw.toString() ); + } + + return buffer; + } + } + + /** {@inheritDoc} */ + public MessageHolder addDebugMessage( CharSequence messagePart, Throwable error ) + { + return addMessage( MessageLevels.LEVEL_DEBUG, messagePart, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addDebugMessage( CharSequence messagePart ) + { + return addMessage( MessageLevels.LEVEL_DEBUG, messagePart ); + } + + /** {@inheritDoc} */ + public MessageHolder addDebugMessage( Throwable error ) + { + return addMessage( MessageLevels.LEVEL_DEBUG, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addErrorMessage( CharSequence messagePart, Throwable error ) + { + return addMessage( MessageLevels.LEVEL_ERROR, messagePart, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addErrorMessage( CharSequence messagePart ) + { + return addMessage( MessageLevels.LEVEL_ERROR, messagePart ); + } + + /** {@inheritDoc} */ + public MessageHolder addErrorMessage( Throwable error ) + { + return addMessage( MessageLevels.LEVEL_ERROR, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addInfoMessage( CharSequence messagePart, Throwable error ) + { + return addMessage( MessageLevels.LEVEL_INFO, messagePart, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addInfoMessage( CharSequence messagePart ) + { + return addMessage( MessageLevels.LEVEL_INFO, messagePart ); + } + + /** {@inheritDoc} */ + public MessageHolder addInfoMessage( Throwable error ) + { + return addMessage( MessageLevels.LEVEL_INFO, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addSevereMessage( CharSequence messagePart, Throwable error ) + { + return addMessage( MessageLevels.LEVEL_SEVERE, messagePart, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addSevereMessage( CharSequence messagePart ) + { + return addMessage( MessageLevels.LEVEL_SEVERE, messagePart ); + } + + /** {@inheritDoc} */ + public MessageHolder addSevereMessage( Throwable error ) + { + return addMessage( MessageLevels.LEVEL_SEVERE, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addWarningMessage( CharSequence messagePart, Throwable error ) + { + return addMessage( MessageLevels.LEVEL_WARNING, messagePart, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addWarningMessage( CharSequence messagePart ) + { + return addMessage( MessageLevels.LEVEL_WARNING, messagePart ); + } + + /** {@inheritDoc} */ + public MessageHolder addWarningMessage( Throwable error ) + { + return addMessage( MessageLevels.LEVEL_WARNING, error ); + } + + /** {@inheritDoc} */ + public int countDebugMessages() + { + return countMessagesOfType( MessageLevels.LEVEL_DEBUG ); + } + + /** {@inheritDoc} */ + public int countErrorMessages() + { + return countMessagesOfType( MessageLevels.LEVEL_ERROR ); + } + + /** {@inheritDoc} */ + public int countInfoMessages() + { + return countMessagesOfType( MessageLevels.LEVEL_INFO ); + } + + /** {@inheritDoc} */ + public int countMessages() + { + return size(); + } + + /** {@inheritDoc} */ + public int countSevereMessages() + { + return countMessagesOfType( MessageLevels.LEVEL_SEVERE ); + } + + /** {@inheritDoc} */ + public int countWarningMessages() + { + return countMessagesOfType( MessageLevels.LEVEL_WARNING ); + } + + /** + * @param messageLevel leve. + * @return number of messages. + */ + private int countMessagesOfType( int messageLevel ) + { + int count = 0; + + for ( Message message : messages ) + { + if ( messageLevel == message.getMessageLevel() ) + { + count++; + } + } + + return count; + } + + /** {@inheritDoc} */ + public boolean isDebugEnabled() + { + return messageLevelStates[MessageLevels.LEVEL_DEBUG]; + } + + /** {@inheritDoc} */ + public boolean isErrorEnabled() + { + return messageLevelStates[MessageLevels.LEVEL_ERROR]; + } + + /** {@inheritDoc} */ + public boolean isInfoEnabled() + { + return messageLevelStates[MessageLevels.LEVEL_INFO]; + } + + /** {@inheritDoc} */ + public boolean isSevereEnabled() + { + return messageLevelStates[MessageLevels.LEVEL_SEVERE]; + } + + /** {@inheritDoc} */ + public boolean isWarningEnabled() + { + return messageLevelStates[MessageLevels.LEVEL_WARNING]; + } + + /** {@inheritDoc} */ + public MessageHolder newDebugMessage() + { + if ( isDebugEnabled() ) + { + newMessage( MessageLevels.LEVEL_DEBUG ); + } + + return this; + } + + /** {@inheritDoc} */ + public MessageHolder newErrorMessage() + { + if ( isErrorEnabled() ) + { + newMessage( MessageLevels.LEVEL_ERROR ); + } + + return this; + } + + /** {@inheritDoc} */ + public MessageHolder newInfoMessage() + { + if ( isInfoEnabled() ) + { + newMessage( MessageLevels.LEVEL_INFO ); + } + + return this; + } + + /** {@inheritDoc} */ + public MessageHolder newSevereMessage() + { + if ( isSevereEnabled() ) + { + newMessage( MessageLevels.LEVEL_SEVERE ); + } + + return this; + } + + /** {@inheritDoc} */ + public MessageHolder newWarningMessage() + { + if ( isWarningEnabled() ) + { + newMessage( MessageLevels.LEVEL_WARNING ); + } + + return this; + } + + /** {@inheritDoc} */ + public void setDebugEnabled( boolean enabled ) + { + messageLevelStates[MessageLevels.LEVEL_DEBUG] = enabled; + } + + /** {@inheritDoc} */ + public void setErrorEnabled( boolean enabled ) + { + messageLevelStates[MessageLevels.LEVEL_ERROR] = enabled; + } + + /** {@inheritDoc} */ + public void setInfoEnabled( boolean enabled ) + { + messageLevelStates[MessageLevels.LEVEL_INFO] = enabled; + } + + /** {@inheritDoc} */ + public void setSevereEnabled( boolean enabled ) + { + messageLevelStates[MessageLevels.LEVEL_SEVERE] = enabled; + } + + /** {@inheritDoc} */ + public void setWarningEnabled( boolean enabled ) + { + messageLevelStates[MessageLevels.LEVEL_WARNING] = enabled; + } + + /** {@inheritDoc} */ + public void flush() + { + if ( onDemandSink != null && currentMessage != null ) + { + renderTo( currentMessage, onDemandSink ); + currentMessage = null; + } + } + + /** {@inheritDoc} */ + public void render( MessageSink sink ) + { + for ( Message message : messages ) + { + renderTo( message, sink ); + } + } + + /** + * @param message {@link Message} + * @param sink {@link MessageSink} + */ + protected void renderTo( Message message, MessageSink sink ) + { + switch ( message.getMessageLevel() ) + { + case ( MessageLevels.LEVEL_SEVERE ): + sink.severe( message.render().toString() ); + break; + + case ( MessageLevels.LEVEL_ERROR ): + sink.error( message.render().toString() ); + break; + + case ( MessageLevels.LEVEL_WARNING ): + sink.warning( message.render().toString() ); + break; + + case ( MessageLevels.LEVEL_INFO ): + sink.info( message.render().toString() ); + break; + + default: + sink.debug( message.render().toString() ); + } + } + +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/MessageHolder.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/MessageHolder.java new file mode 100644 index 000000000..be4f83394 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/MessageHolder.java @@ -0,0 +1,290 @@ +package org.apache.maven.shared.io.logging; + +/* + * 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. + */ + +/** + * Message Holder class. + * + */ +public interface MessageHolder +{ + + /** + * @return {@link MessageHolder} + */ + MessageHolder newMessage(); + + /** + * @return {@link MessageHolder} + */ + MessageHolder newDebugMessage(); + + /** + * @return {@link MessageHolder} + */ + MessageHolder newInfoMessage(); + + /** + * @return {@link MessageHolder} + */ + MessageHolder newWarningMessage(); + + /** + * @return {@link MessageHolder} + */ + MessageHolder newErrorMessage(); + + /** + * @return {@link MessageHolder} + */ + MessageHolder newSevereMessage(); + + /** + * @param messagePart message part. + * @return {@link MessageHolder} + */ + MessageHolder append( CharSequence messagePart ); + + /** + * @param error {@link Throwable} + * @return {@link MessageHolder} + */ + MessageHolder append( Throwable error ); + + /** + * @param messagePart Message Part. + * @param error {@link Throwable} + * @return {@link MessageHolder} + */ + MessageHolder addMessage( CharSequence messagePart, Throwable error ); + + /** + * @param messagePart message part. + * @return {@link MessageHolder} + */ + MessageHolder addMessage( CharSequence messagePart ); + + /** + * @param error {@link Throwable} + * @return {@link MessageHolder} + */ + MessageHolder addMessage( Throwable error ); + + /** + * @param messagePart message part. + * @param error {@link Throwable} + * @return {@link MessageHolder} + */ + MessageHolder addDebugMessage( CharSequence messagePart, Throwable error ); + + /** + * @param messagePart messages part. + * @return {@link MessageHolder} + */ + MessageHolder addDebugMessage( CharSequence messagePart ); + + /** + * @param error messages part. + * @return {@link MessageHolder} + */ + MessageHolder addDebugMessage( Throwable error ); + + /** + * @param messagePart message part. + * @param error {@link Throwable} + * @return {@link MessageHolder} + */ + MessageHolder addInfoMessage( CharSequence messagePart, Throwable error ); + + /** + * @param messagePart messages part. + * @return {@link MessageHolder} + */ + MessageHolder addInfoMessage( CharSequence messagePart ); + + /** + * @param error {@link Throwable} + * @return {@link MessageHolder} + */ + MessageHolder addInfoMessage( Throwable error ); + + /** + * @param messagePart message part. + * @param error {@link Throwable} + * @return {@link MessageHolder} + */ + MessageHolder addWarningMessage( CharSequence messagePart, Throwable error ); + + /** + * @param messagePart message part. + * @return {@link MessageHolder} + */ + MessageHolder addWarningMessage( CharSequence messagePart ); + + /** + * @param error {@link Throwable} + * @return {@link MessageHolder} + */ + MessageHolder addWarningMessage( Throwable error ); + + /** + * @param messagePart message part. + * @param error {@link Throwable} + * @return {@link MessageHolder} + */ + MessageHolder addErrorMessage( CharSequence messagePart, Throwable error ); + + /** + * @param messagePart message part. + * @return {@link MessageHolder} + */ + MessageHolder addErrorMessage( CharSequence messagePart ); + + /** + * @param error {@link Throwable} + * @return {@link MessageHolder} + */ + MessageHolder addErrorMessage( Throwable error ); + + /** + * @param messagePart message part. + * @param error {@link Throwable} + * @return {@link MessageHolder} + */ + MessageHolder addSevereMessage( CharSequence messagePart, Throwable error ); + + /** + * @param messagePart message part. + * @return {@link MessageHolder} + */ + MessageHolder addSevereMessage( CharSequence messagePart ); + + /** + * @param error The error. + * @return {@link MessageHolder} + */ + MessageHolder addSevereMessage( Throwable error ); + + /** + * @return the size. + */ + int size(); + + /** + * @return count number of messages. + */ + int countMessages(); + + /** + * @return count number of debug messages. + */ + int countDebugMessages(); + + /** + * @return count number of info messages. + */ + int countInfoMessages(); + + /** + * @return count number of warning messages. + */ + int countWarningMessages(); + + /** + * @return count number of error messages. + */ + int countErrorMessages(); + + /** + * @return count number of server messages. + */ + int countSevereMessages(); + + /** + * @return true / false. + */ + boolean isDebugEnabled(); + + /** + * @param enabled enable debug + */ + void setDebugEnabled( boolean enabled ); + + /** + * @return true if info is enabled false otherwise. + */ + boolean isInfoEnabled(); + + /** + * @param enabled true info enable false otherwise. + */ + void setInfoEnabled( boolean enabled ); + + /** + * @return true if warning is enabled false otherwise. + */ + boolean isWarningEnabled(); + + /** + * @param enabled enable warning or disable. + */ + void setWarningEnabled( boolean enabled ); + + /** + * @return true if error is enabled false otherwise. + */ + boolean isErrorEnabled(); + + /** + * @param enabled enable error or disable. + */ + void setErrorEnabled( boolean enabled ); + + /** + * @return true if server is enabled false otherwise. + */ + boolean isSevereEnabled(); + + /** + * @param enabled enable server or disable. + */ + void setSevereEnabled( boolean enabled ); + + /** + * @return true if empty false otherwise. + */ + boolean isEmpty(); + + /** + * @return rendered. + */ + String render(); + + /** + * @param sink {@link MessageSink} + */ + void render( MessageSink sink ); + + /** + * flush. + */ + void flush(); + +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/MessageLevels.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/MessageLevels.java new file mode 100644 index 000000000..06fe3de87 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/MessageLevels.java @@ -0,0 +1,117 @@ +package org.apache.maven.shared.io.logging; + +/* + * 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. + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * + */ +public final class MessageLevels +{ + + /** + * Debug. + */ + public static final int LEVEL_DEBUG = 0; + /** + * Info + */ + public static final int LEVEL_INFO = 1; + /** + * Warning. + */ + public static final int LEVEL_WARNING = 2; + /** + * Error + */ + public static final int LEVEL_ERROR = 3; + /** + * Severe + */ + public static final int LEVEL_SEVERE = 4; + /** + * Disabled. + */ + public static final int LEVEL_DISABLED = 5; + + private static final List LEVEL_NAMES; + + static + { + List names = new ArrayList(); + names.add( "DEBUG" ); + names.add( "INFO" ); + names.add( "WARN" ); + names.add( "ERROR" ); + names.add( "SEVERE" ); + + LEVEL_NAMES = Collections.unmodifiableList( names ); + } + + private MessageLevels() + { + } + + /** + * @param maxMessageLevel for which level. + * @return level states. + */ + public static boolean[] getLevelStates( int maxMessageLevel ) + { + boolean[] states = new boolean[5]; + + Arrays.fill( states, false ); + + switch ( maxMessageLevel ) + { + case ( LEVEL_DEBUG ): + states[LEVEL_DEBUG] = true; + case ( LEVEL_INFO ): + states[LEVEL_INFO] = true; + case ( LEVEL_WARNING ): + states[LEVEL_WARNING] = true; + case ( LEVEL_ERROR ): + states[LEVEL_ERROR] = true; + case ( LEVEL_SEVERE ): + states[LEVEL_SEVERE] = true; + default: + } + + return states; + } + + /** + * @param messageLevel the message leve. + * @return The label. + */ + public static String getLevelLabel( int messageLevel ) + { + if ( messageLevel > -1 && LEVEL_NAMES.size() > messageLevel ) + { + return (String) LEVEL_NAMES.get( messageLevel ); + } + + throw new IllegalArgumentException( "Invalid message level: " + messageLevel ); + } +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/MessageSink.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/MessageSink.java new file mode 100644 index 000000000..3856e2158 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/MessageSink.java @@ -0,0 +1,55 @@ +package org.apache.maven.shared.io.logging; + +/* + * 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. + */ + + +/** + * Message Sink interface. + * + */ +public interface MessageSink +{ + + /** + * @param message The message. + */ + void debug( String message ); + + /** + * @param message The message. + */ + void info( String message ); + + /** + * @param message The message. + */ + void warning( String message ); + + /** + * @param message The message. + */ + void error( String message ); + + /** + * @param message The message. + */ + void severe( String message ); + +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/MojoLogSink.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/MojoLogSink.java new file mode 100644 index 000000000..f98e818ca --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/MojoLogSink.java @@ -0,0 +1,73 @@ +package org.apache.maven.shared.io.logging; + +/* + * 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. + */ + +import org.apache.maven.plugin.logging.Log; + + +/** + * The Mojo Log Sink. + * + */ +public class MojoLogSink + implements MessageSink +{ + + private final Log logger; + + /** + * @param logger {@link Log} + */ + public MojoLogSink( Log logger ) + { + this.logger = logger; + } + + /** {@inheritDoc} */ + public void debug( String message ) + { + logger.debug( message ); + } + + /** {@inheritDoc} */ + public void error( String message ) + { + logger.error( message ); + } + + /** {@inheritDoc} */ + public void info( String message ) + { + logger.info( message ); + } + + /** {@inheritDoc} */ + public void severe( String message ) + { + logger.error( message ); + } + + /** {@inheritDoc} */ + public void warning( String message ) + { + logger.warn( message ); + } + +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/PlexusLoggerSink.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/PlexusLoggerSink.java new file mode 100644 index 000000000..e49374c13 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/logging/PlexusLoggerSink.java @@ -0,0 +1,71 @@ +package org.apache.maven.shared.io.logging; + +/* + * 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. + */ + +import org.codehaus.plexus.logging.Logger; + +/** + * The plexus logger sink implementation. + */ +public class PlexusLoggerSink + implements MessageSink +{ + + private final Logger logger; + + /** + * @param logger The logger. + */ + public PlexusLoggerSink( Logger logger ) + { + this.logger = logger; + } + + /** {@inheritDoc} */ + public void debug( String message ) + { + logger.debug( message ); + } + + /** {@inheritDoc} */ + public void error( String message ) + { + logger.error( message ); + } + + /** {@inheritDoc} */ + public void info( String message ) + { + logger.info( message ); + } + + /** {@inheritDoc} */ + public void severe( String message ) + { + logger.fatalError( message ); + } + + /** {@inheritDoc} */ + public void warning( String message ) + { + logger.warn( message ); + } + +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/AbstractResourceInclusionScanner.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/AbstractResourceInclusionScanner.java new file mode 100644 index 000000000..2f05f091a --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/AbstractResourceInclusionScanner.java @@ -0,0 +1,95 @@ +package org.apache.maven.shared.io.scan; + +/* + * 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. + */ + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.apache.maven.shared.io.scan.mapping.SourceMapping; +import org.apache.maven.shared.utils.io.DirectoryScanner; + +/** + * @author jdcasey + * @version $Id$ + */ +public abstract class AbstractResourceInclusionScanner + implements ResourceInclusionScanner +{ + private final List sourceMappings = new ArrayList(); + + /** {@inheritDoc} */ + public final void addSourceMapping( SourceMapping sourceMapping ) + { + sourceMappings.add( sourceMapping ); + } + + /** + * @return The source mapping. + */ + protected final List getSourceMappings() + { + return Collections.unmodifiableList( sourceMappings ); + } + + /** + * @param sourceDir {@link File} + * @param sourceIncludes source includes. + * @param sourceExcludes source excludes. + * @return The resulting sources. + */ + protected String[] scanForSources( File sourceDir, Set sourceIncludes, Set sourceExcludes ) + { + DirectoryScanner ds = new DirectoryScanner(); + ds.setFollowSymlinks( true ); + ds.setBasedir( sourceDir ); + + String[] includes; + if ( sourceIncludes.isEmpty() ) + { + includes = new String[0]; + } + else + { + includes = (String[]) sourceIncludes.toArray( new String[sourceIncludes.size()] ); + } + + ds.setIncludes( includes ); + + String[] excludes; + if ( sourceExcludes.isEmpty() ) + { + excludes = new String[0]; + } + else + { + excludes = (String[]) sourceExcludes.toArray( new String[sourceExcludes.size()] ); + } + + ds.setExcludes( excludes ); + ds.addDefaultExcludes(); + + ds.scan(); + + return ds.getIncludedFiles(); + } +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/InclusionScanException.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/InclusionScanException.java new file mode 100644 index 000000000..88434277e --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/InclusionScanException.java @@ -0,0 +1,45 @@ +package org.apache.maven.shared.io.scan; + +/* + * 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. + */ + +/** + * @author jdcasey + * @version $Id$ + */ +public class InclusionScanException + extends Exception +{ + /** + * @param message The message. + */ + public InclusionScanException( String message ) + { + super( message ); + } + + /** + * @param message The message. + * @param cause The cause of the error. + */ + public InclusionScanException( String message, Throwable cause ) + { + super( message, cause ); + } +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/ResourceInclusionScanner.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/ResourceInclusionScanner.java new file mode 100644 index 000000000..51711249d --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/ResourceInclusionScanner.java @@ -0,0 +1,46 @@ +package org.apache.maven.shared.io.scan; + +/* + * 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. + */ + +import org.apache.maven.shared.io.scan.mapping.SourceMapping; + +import java.io.File; +import java.util.Set; + +/** + * @author jdcasey + * @version $Id$ + */ +public interface ResourceInclusionScanner +{ + /** + * @param sourceMapping {@link SourceMapping} + */ + void addSourceMapping( SourceMapping sourceMapping ); + + /** + * @param sourceDir {@link File} + * @param targetDir {@link File} + * @return The included sources. + * @throws InclusionScanException in case of an error. + */ + Set getIncludedSources( File sourceDir, File targetDir ) + throws InclusionScanException; +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/SimpleResourceInclusionScanner.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/SimpleResourceInclusionScanner.java new file mode 100644 index 000000000..c0aed2535 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/SimpleResourceInclusionScanner.java @@ -0,0 +1,64 @@ +package org.apache.maven.shared.io.scan; + +/* + * 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. + */ + +import java.io.File; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.apache.maven.shared.io.scan.mapping.SourceMapping; + +/** + * @author Trygve Laugstøl + * @version $Id$ + */ +public class SimpleResourceInclusionScanner + extends AbstractResourceInclusionScanner +{ + private Set sourceIncludes; + + private Set sourceExcludes; + + /** + * @param sourceIncludes The source includes. + * @param sourceExcludes The source excludes. + */ + public SimpleResourceInclusionScanner( Set sourceIncludes, Set sourceExcludes ) + { + this.sourceIncludes = sourceIncludes; + + this.sourceExcludes = sourceExcludes; + } + + /** {@inheritDoc} */ + public Set getIncludedSources( File sourceDir, File targetDir ) + throws InclusionScanException + { + List srcMappings = getSourceMappings(); + + if ( srcMappings.isEmpty() ) + { + return Collections.emptySet(); + } + + return Collections.singleton( scanForSources( sourceDir, sourceIncludes, sourceExcludes ) ); + } +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/StaleResourceScanner.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/StaleResourceScanner.java new file mode 100644 index 000000000..62358bead --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/StaleResourceScanner.java @@ -0,0 +1,123 @@ +package org.apache.maven.shared.io.scan; + +/* + * 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. + */ + +import java.io.File; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.maven.shared.io.scan.mapping.SourceMapping; + +/** + * @author jdcasey + * @version $Id$ + */ +public class StaleResourceScanner + extends AbstractResourceInclusionScanner +{ + private final long lastUpdatedWithinMsecs; + + private final Set sourceIncludes; + + private final Set sourceExcludes; + + // ---------------------------------------------------------------------- + // + // ---------------------------------------------------------------------- + + /** + * Create instance with defaults. + */ + public StaleResourceScanner() + { + this( 0, Collections.singleton( "**/*" ), Collections.emptySet() ); + } + + /** + * @param lastUpdatedWithinMsecs last update within milli seconds. + */ + public StaleResourceScanner( long lastUpdatedWithinMsecs ) + { + this( lastUpdatedWithinMsecs, Collections.singleton( "**/*" ), Collections.emptySet() ); + } + + /** + * @param lastUpdatedWithinMsecs last update within milli seconds. + * @param sourceIncludes source includes. + * @param sourceExcludes source excludes. + */ + public StaleResourceScanner( long lastUpdatedWithinMsecs, Set sourceIncludes, Set sourceExcludes ) + { + this.lastUpdatedWithinMsecs = lastUpdatedWithinMsecs; + + this.sourceIncludes = sourceIncludes; + + this.sourceExcludes = sourceExcludes; + } + + // ---------------------------------------------------------------------- + // SourceInclusionScanner Implementation + // ---------------------------------------------------------------------- + + /** {@inheritDoc} */ + public Set getIncludedSources( File sourceDir, File targetDir ) + throws InclusionScanException + { + List srcMappings = getSourceMappings(); + + if ( srcMappings.isEmpty() ) + { + return Collections.emptySet(); + } + + String[] potentialIncludes = scanForSources( sourceDir, sourceIncludes, sourceExcludes ); + + Set matchingSources = new HashSet(); + + for ( int i = 0; i < potentialIncludes.length; i++ ) + { + String path = potentialIncludes[i]; + + File sourceFile = new File( sourceDir, path ); + + staleSourceFileTesting: for ( SourceMapping mapping : srcMappings ) + { + Set targetFiles = mapping.getTargetFiles( targetDir, path ); + + // never include files that don't have corresponding target mappings. + // the targets don't have to exist on the filesystem, but the + // mappers must tell us to look for them. + for ( File targetFile : targetFiles ) + { + if ( !targetFile.exists() + || ( targetFile.lastModified() + lastUpdatedWithinMsecs < sourceFile.lastModified() ) ) + { + matchingSources.add( sourceFile ); + break staleSourceFileTesting; + } + } + } + } + + return matchingSources; + } +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/mapping/SingleTargetMapping.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/mapping/SingleTargetMapping.java new file mode 100644 index 000000000..2d1f3378a --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/mapping/SingleTargetMapping.java @@ -0,0 +1,63 @@ +package org.apache.maven.shared.io.scan.mapping; + +/* + * 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. + */ + +import org.apache.maven.shared.io.scan.InclusionScanException; + +import java.util.Set; +import java.util.Collections; +import java.io.File; + +/** + * Maps a set of input files to a single output file. + * + * @author Trygve Laugstøl + * @version $Id$ + */ +public class SingleTargetMapping + implements SourceMapping +{ + private String sourceSuffix; + + private String outputFile; + + /** + * @param sourceSuffix source suffix. + * @param outputFile output file. + */ + public SingleTargetMapping( String sourceSuffix, String outputFile ) + { + this.sourceSuffix = sourceSuffix; + + this.outputFile = outputFile; + } + + /** {@inheritDoc} */ + public Set getTargetFiles( File targetDir, String source ) + throws InclusionScanException + { + if ( !source.endsWith( sourceSuffix ) ) + { + return Collections.emptySet(); + } + + return Collections.singleton( new File( targetDir, outputFile ) ); + } +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/mapping/SourceMapping.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/mapping/SourceMapping.java new file mode 100644 index 000000000..7defc0ba4 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/mapping/SourceMapping.java @@ -0,0 +1,41 @@ +package org.apache.maven.shared.io.scan.mapping; + +/* + * 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. + */ + +import java.io.File; +import java.util.Set; + +import org.apache.maven.shared.io.scan.InclusionScanException; + +/** + * @author jdcasey + * @version $Id$ + */ +public interface SourceMapping +{ + /** + * @param targetDir target directory. + * @param source source. + * @return list of target files. + * @throws InclusionScanException in case of an error. + */ + Set getTargetFiles( File targetDir, String source ) + throws InclusionScanException; +} diff --git a/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/mapping/SuffixMapping.java b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/mapping/SuffixMapping.java new file mode 100644 index 000000000..75aa461fd --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/java/org/apache/maven/shared/io/scan/mapping/SuffixMapping.java @@ -0,0 +1,77 @@ +package org.apache.maven.shared.io.scan.mapping; + +/* + * 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. + */ + +import java.io.File; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * @author jdcasey + * @version $Id$ + */ +public final class SuffixMapping + implements SourceMapping +{ + private final String sourceSuffix; + + private final Set targetSuffixes; + + /** + * @param sourceSuffix source suffix. + * @param targetSuffix target suffix. + */ + public SuffixMapping( String sourceSuffix, String targetSuffix ) + { + this.sourceSuffix = sourceSuffix; + + this.targetSuffixes = Collections.singleton( targetSuffix ); + } + + /** + * @param sourceSuffix source suffix. + * @param targetSuffixes target suffixes. + */ + public SuffixMapping( String sourceSuffix, Set targetSuffixes ) + { + this.sourceSuffix = sourceSuffix; + + this.targetSuffixes = targetSuffixes; + } + + /** {@inheritDoc} */ + public Set getTargetFiles( File targetDir, String source ) + { + Set targetFiles = new HashSet(); + + if ( source.endsWith( sourceSuffix ) ) + { + String base = source.substring( 0, source.length() - sourceSuffix.length() ); + + for ( String suffix : targetSuffixes ) + { + targetFiles.add( new File( targetDir, base + suffix ) ); + } + } + + return targetFiles; + } +} diff --git a/Java-base/maven-shared-io/src/src/main/resources/META-INF/plexus/components.xml b/Java-base/maven-shared-io/src/src/main/resources/META-INF/plexus/components.xml new file mode 100644 index 000000000..648a391b9 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/main/resources/META-INF/plexus/components.xml @@ -0,0 +1,33 @@ + + + + + + org.apache.maven.shared.io.download.DownloadManager + default + org.apache.maven.shared.io.download.DefaultDownloadManager + + + org.apache.maven.artifact.manager.WagonManager + + + + + \ No newline at end of file diff --git a/Java-base/maven-shared-io/src/src/site/resources/download.cgi b/Java-base/maven-shared-io/src/src/site/resources/download.cgi new file mode 100644 index 000000000..1b178d2e6 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/site/resources/download.cgi @@ -0,0 +1,22 @@ +#!/bin/sh +# +# 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. +# +# Just call the standard mirrors.cgi script. It will use download.html +# as the input template. +exec /www/www.apache.org/dyn/mirrors/mirrors.cgi $* \ No newline at end of file diff --git a/Java-base/maven-shared-io/src/src/site/site.xml b/Java-base/maven-shared-io/src/src/site/site.xml new file mode 100644 index 000000000..a18a2a646 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/site/site.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Java-base/maven-shared-io/src/src/site/xdoc/download.xml.vm b/Java-base/maven-shared-io/src/src/site/xdoc/download.xml.vm new file mode 100644 index 000000000..666d997c4 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/site/xdoc/download.xml.vm @@ -0,0 +1,126 @@ + + + + + + + Download ${project.name} Source + + +
+ +

${project.name} ${project.version} is distributed in source format. Use a source archive if you intend to build + ${project.name} yourself. Otherwise, simply use the ready-made binary artifacts from central repository.

+ +

You will be prompted for a mirror - if the file is not found on yours, please be patient, as it may take 24 + hours to reach all mirrors.

+ +

In order to guard against corrupted downloads/installations, it is highly recommended to + verify the signature + of the release bundles against the public KEYS used by the Apache Maven + developers.

+ +

${project.name} is distributed under the Apache License, version 2.0.

+ +

We strongly encourage our users to configure a Maven repository mirror closer to their location, please read How to Use Mirrors for Repositories.

+ + + + +

+ [if-any logo] + + logo + + [end] + The currently selected mirror is + [preferred]. + If you encounter a problem with this mirror, + please select another mirror. + If all mirrors are failing, there are + backup + mirrors + (at the end of the mirrors list) that should be available. +

+ +
+ Other mirrors: + + +
+ +

+ You may also consult the + complete list of + mirrors. +

+ + + + + +

This is the current stable version of ${project.name}.

+ + + + + + + + + + + + + + + + + + +
LinkChecksumSignature
${project.name} ${project.version} (Source zip)maven/shared/${project.artifactId}-${project.version}-source-release.zipmaven/shared/${project.artifactId}-${project.version}-source-release.zip.sha512maven/shared/${project.artifactId}-${project.version}-source-release.zip.asc
+
+ + + +

Older non-recommended releases can be found on our archive site.

+ +
+
+ +
+ diff --git a/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/Utils.java b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/Utils.java new file mode 100644 index 000000000..59e6c7f17 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/Utils.java @@ -0,0 +1,55 @@ +package org.apache.maven.shared.io; + +/* + * 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. + */ + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; + +import org.apache.maven.shared.utils.WriterFactory; + +public final class Utils +{ + + private Utils() + { + } + + public static void writeFileWithEncoding( File file, String content, String encoding ) + throws IOException + { + try ( Writer writer = WriterFactory.newWriter( file, encoding )) + { + writer.write( content ); + } + } + + public static String toString( Throwable error ) + { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter( sw ); + + error.printStackTrace( pw ); + + return sw.toString(); + } +} diff --git a/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/download/DefaultDownloadManagerTest.java b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/download/DefaultDownloadManagerTest.java new file mode 100644 index 000000000..f84608948 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/download/DefaultDownloadManagerTest.java @@ -0,0 +1,559 @@ +package org.apache.maven.shared.io.download; + +/* + * 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. + */ + +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.anyString; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; + +import org.apache.maven.artifact.manager.WagonManager; +import org.apache.maven.shared.io.Utils; +import org.apache.maven.shared.io.logging.DefaultMessageHolder; +import org.apache.maven.shared.io.logging.MessageHolder; +import org.apache.maven.wagon.ConnectionException; +import org.apache.maven.wagon.ResourceDoesNotExistException; +import org.apache.maven.wagon.TransferFailedException; +import org.apache.maven.wagon.UnsupportedProtocolException; +import org.apache.maven.wagon.Wagon; +import org.apache.maven.wagon.authentication.AuthenticationException; +import org.apache.maven.wagon.authentication.AuthenticationInfo; +import org.apache.maven.wagon.authorization.AuthorizationException; +import org.apache.maven.wagon.events.TransferListener; +import org.apache.maven.wagon.proxy.ProxyInfo; +import org.apache.maven.wagon.repository.Repository; +import org.codehaus.plexus.PlexusTestCase; + +public class DefaultDownloadManagerTest + extends PlexusTestCase +{ + + private WagonManager wagonManager; + + private Wagon wagon; + + public void setUp() + throws Exception + { + super.setUp(); + + wagonManager = createMock( WagonManager.class ); + wagon = createMock( Wagon.class ); + } + + public void testShouldConstructWithNoParamsAndHaveNonNullMessageHolder() + { + new DefaultDownloadManager(); + } + + public void testShouldConstructWithWagonManager() + { + replay( wagonManager ); + + new DefaultDownloadManager( wagonManager ); + + verify( wagonManager ); + } + + public void testShouldLookupInstanceDefaultRoleHint() + throws Exception + { + lookup( DownloadManager.ROLE, DefaultDownloadManager.ROLE_HINT ); + } + + public void testShouldFailToDownloadMalformedURL() + { + replay( wagonManager ); + + DownloadManager mgr = new DefaultDownloadManager( wagonManager ); + + try + { + mgr.download( "://nothing.com/index.html", new DefaultMessageHolder() ); + + fail( "Should not download with invalid URL." ); + } + catch ( DownloadFailedException e ) + { + assertTrue( e.getMessage().indexOf( "invalid URL" ) > -1 ); + } + + verify( wagonManager ); + } + + public void testShouldDownloadFromTempFileWithNoTransferListeners() + throws IOException, DownloadFailedException + { + File tempFile = File.createTempFile( "download-source", "test" ); + tempFile.deleteOnExit(); + + setupDefaultMockConfiguration(); + + replay( wagon, wagonManager ); + + DownloadManager downloadManager = new DefaultDownloadManager( wagonManager ); + + downloadManager.download( tempFile.toURL().toExternalForm(), new DefaultMessageHolder() ); + + verify( wagon, wagonManager ); + } + + public void testShouldDownloadFromTempFileTwiceAndUseCache() + throws IOException, DownloadFailedException + { + File tempFile = File.createTempFile( "download-source", "test" ); + tempFile.deleteOnExit(); + + setupDefaultMockConfiguration(); + + replay( wagon, wagonManager ); + + DownloadManager downloadManager = new DefaultDownloadManager( wagonManager ); + + File first = downloadManager.download( tempFile.toURL().toExternalForm(), new DefaultMessageHolder() ); + + MessageHolder mh = new DefaultMessageHolder(); + + File second = downloadManager.download( tempFile.toURL().toExternalForm(), mh ); + + assertSame( first, second ); + assertEquals( 1, mh.size() ); + assertTrue( mh.render().indexOf( "Using cached" ) > -1 ); + + verify( wagon, wagonManager ); + } + + public void testShouldDownloadFromTempFileWithOneTransferListener() + throws IOException, DownloadFailedException + { + File tempFile = File.createTempFile( "download-source", "test" ); + tempFile.deleteOnExit(); + + setupDefaultMockConfiguration(); + + TransferListener transferListener = createMock( TransferListener.class ); + + wagon.addTransferListener( transferListener ); + + wagon.removeTransferListener( transferListener ); + + replay( wagon, wagonManager, transferListener ); + + DownloadManager downloadManager = new DefaultDownloadManager( wagonManager ); + + downloadManager.download( tempFile.toURL().toExternalForm(), Collections.singletonList( transferListener ), + new DefaultMessageHolder() ); + + verify( wagon, wagonManager, transferListener ); + } + + public void testShouldFailToDownloadWhenWagonProtocolNotFound() + throws IOException + { + File tempFile = File.createTempFile( "download-source", "test" ); + tempFile.deleteOnExit(); + + setupMocksWithWagonManagerGetException( new UnsupportedProtocolException( "not supported" ) ); + + replay( wagon, wagonManager ); + + DownloadManager downloadManager = new DefaultDownloadManager( wagonManager ); + + try + { + downloadManager.download( tempFile.toURL().toExternalForm(), new DefaultMessageHolder() ); + + fail( "should have failed to retrieve wagon." ); + } + catch ( DownloadFailedException e ) + { + assertTrue( Utils.toString( e ).indexOf( "UnsupportedProtocolException" ) > -1 ); + } + + verify( wagon, wagonManager ); + } + + public void testShouldFailToDownloadWhenWagonConnectThrowsConnectionException() + throws IOException + { + File tempFile = File.createTempFile( "download-source", "test" ); + tempFile.deleteOnExit(); + + setupMocksWithWagonConnectionException( new ConnectionException( "connect error" ) ); + + replay( wagon, wagonManager ); + + DownloadManager downloadManager = new DefaultDownloadManager( wagonManager ); + + try + { + downloadManager.download( tempFile.toURL().toExternalForm(), new DefaultMessageHolder() ); + + fail( "should have failed to connect wagon." ); + } + catch ( DownloadFailedException e ) + { + assertTrue( Utils.toString( e ).indexOf( "ConnectionException" ) > -1 ); + } + + verify( wagon, wagonManager ); + } + + public void testShouldFailToDownloadWhenWagonConnectThrowsAuthenticationException() + throws IOException + { + File tempFile = File.createTempFile( "download-source", "test" ); + tempFile.deleteOnExit(); + + setupMocksWithWagonConnectionException( new AuthenticationException( "bad credentials" ) ); + + replay( wagon, wagonManager ); + + DownloadManager downloadManager = new DefaultDownloadManager( wagonManager ); + + try + { + downloadManager.download( tempFile.toURL().toExternalForm(), new DefaultMessageHolder() ); + + fail( "should have failed to connect wagon." ); + } + catch ( DownloadFailedException e ) + { + assertTrue( Utils.toString( e ).indexOf( "AuthenticationException" ) > -1 ); + } + + verify( wagon, wagonManager ); + } + + public void testShouldFailToDownloadWhenWagonGetThrowsTransferFailedException() + throws IOException + { + File tempFile = File.createTempFile( "download-source", "test" ); + tempFile.deleteOnExit(); + + setupMocksWithWagonGetException( new TransferFailedException( "bad transfer" ) ); + + replay( wagon, wagonManager ); + + DownloadManager downloadManager = new DefaultDownloadManager( wagonManager ); + + try + { + downloadManager.download( tempFile.toURL().toExternalForm(), new DefaultMessageHolder() ); + + fail( "should have failed to get resource." ); + } + catch ( DownloadFailedException e ) + { + assertTrue( Utils.toString( e ).indexOf( "TransferFailedException" ) > -1 ); + } + + verify( wagon, wagonManager ); + } + + public void testShouldFailToDownloadWhenWagonGetThrowsResourceDoesNotExistException() + throws IOException + { + File tempFile = File.createTempFile( "download-source", "test" ); + tempFile.deleteOnExit(); + + setupMocksWithWagonGetException( new ResourceDoesNotExistException( "bad resource" ) ); + + replay( wagon, wagonManager ); + + DownloadManager downloadManager = new DefaultDownloadManager( wagonManager ); + + try + { + downloadManager.download( tempFile.toURL().toExternalForm(), new DefaultMessageHolder() ); + + fail( "should have failed to get resource." ); + } + catch ( DownloadFailedException e ) + { + assertTrue( Utils.toString( e ).indexOf( "ResourceDoesNotExistException" ) > -1 ); + } + + verify( wagon, wagonManager ); + } + + public void testShouldFailToDownloadWhenWagonGetThrowsAuthorizationException() + throws IOException + { + File tempFile = File.createTempFile( "download-source", "test" ); + tempFile.deleteOnExit(); + + setupMocksWithWagonGetException( new AuthorizationException( "bad transfer" ) ); + + replay( wagon, wagonManager ); + + DownloadManager downloadManager = new DefaultDownloadManager( wagonManager ); + + try + { + downloadManager.download( tempFile.toURL().toExternalForm(), new DefaultMessageHolder() ); + + fail( "should have failed to get resource." ); + } + catch ( DownloadFailedException e ) + { + assertTrue( Utils.toString( e ).indexOf( "AuthorizationException" ) > -1 ); + } + + verify( wagon, wagonManager ); + } + + public void testShouldFailToDownloadWhenWagonDisconnectThrowsConnectionException() + throws IOException, DownloadFailedException + { + File tempFile = File.createTempFile( "download-source", "test" ); + tempFile.deleteOnExit(); + + setupMocksWithWagonDisconnectException( new ConnectionException( "not connected" ) ); + + replay( wagon, wagonManager ); + + DownloadManager downloadManager = new DefaultDownloadManager( wagonManager ); + + MessageHolder mh = new DefaultMessageHolder(); + + downloadManager.download( tempFile.toURL().toExternalForm(), mh ); + + assertTrue( mh.render().indexOf( "ConnectionException" ) > -1 ); + + verify( wagon, wagonManager ); + } + + private void setupDefaultMockConfiguration() + { + try + { + expect( wagonManager.getWagon( "file" ) ).andReturn( wagon ); + } + catch ( UnsupportedProtocolException e ) + { + fail( "This shouldn't happen!!" ); + } + + expect( wagonManager.getAuthenticationInfo( anyString() ) ).andReturn( null ); + + expect( wagonManager.getProxy( anyString() ) ).andReturn( null ); + + try + { + wagon.connect( anyObject( Repository.class ) , anyObject( AuthenticationInfo.class ), anyObject( ProxyInfo.class ) ); + } + catch ( ConnectionException e ) + { + fail( "This shouldn't happen!!" ); + } + catch ( AuthenticationException e ) + { + fail( "This shouldn't happen!!" ); + } + + try + { + wagon.get( anyString(), anyObject( File.class ) ); + } + catch ( TransferFailedException e ) + { + fail( "This shouldn't happen!!" ); + } + catch ( ResourceDoesNotExistException e ) + { + fail( "This shouldn't happen!!" ); + } + catch ( AuthorizationException e ) + { + fail( "This shouldn't happen!!" ); + } + + try + { + wagon.disconnect(); + } + catch ( ConnectionException e ) + { + fail( "This shouldn't happen!!" ); + } + } + + private void setupMocksWithWagonManagerGetException( Throwable error ) + { + try + { + expect( wagonManager.getWagon( "file" ) ).andThrow( error ); + } + catch ( UnsupportedProtocolException e ) + { + fail( "This shouldn't happen!!" ); + } + } + + private void setupMocksWithWagonConnectionException( Throwable error ) + { + try + { + expect( wagonManager.getWagon( "file" ) ).andReturn( wagon ); + } + catch ( UnsupportedProtocolException e ) + { + fail( "This shouldn't happen!!" ); + } + + expect( wagonManager.getAuthenticationInfo( anyString() ) ).andReturn( null ); + + expect( wagonManager.getProxy( anyString() ) ).andReturn( null ); + + try + { + wagon.connect( anyObject( Repository.class ) , anyObject( AuthenticationInfo.class ), anyObject( ProxyInfo.class ) ); + expectLastCall().andThrow( error ); + } + catch ( ConnectionException e ) + { + fail( "This shouldn't happen!!" ); + } + catch ( AuthenticationException e ) + { + fail( "This shouldn't happen!!" ); + } + } + + private void setupMocksWithWagonGetException( Throwable error ) + { + try + { + expect( wagonManager.getWagon( "file" ) ).andReturn( wagon ); + } + catch ( UnsupportedProtocolException e ) + { + fail( "This shouldn't happen!!" ); + } + + expect( wagonManager.getAuthenticationInfo( anyString() ) ).andReturn( null ); + + expect( wagonManager.getProxy( anyString() ) ).andReturn( null ); + + try + { + wagon.connect( anyObject( Repository.class ) , anyObject( AuthenticationInfo.class ), anyObject( ProxyInfo.class ) ); + } + catch ( ConnectionException e ) + { + fail( "This shouldn't happen!!" ); + } + catch ( AuthenticationException e ) + { + fail( "This shouldn't happen!!" ); + } + + try + { + wagon.get( anyString(), anyObject( File.class ) ); + expectLastCall().andThrow( error ); + } + catch ( TransferFailedException e ) + { + fail( "This shouldn't happen!!" ); + } + catch ( ResourceDoesNotExistException e ) + { + fail( "This shouldn't happen!!" ); + } + catch ( AuthorizationException e ) + { + fail( "This shouldn't happen!!" ); + } + + try + { + wagon.disconnect(); + } + catch ( ConnectionException e ) + { + fail( "This shouldn't happen!!" ); + } + } + + private void setupMocksWithWagonDisconnectException( Throwable error ) + { + try + { + expect( wagonManager.getWagon( "file" ) ).andReturn( wagon ); + } + catch ( UnsupportedProtocolException e ) + { + fail( "This shouldn't happen!!" ); + } + + expect( wagonManager.getAuthenticationInfo( anyString() ) ).andReturn( null ); + + expect( wagonManager.getProxy( anyString() ) ).andReturn( null ); + + try + { + wagon.connect( anyObject( Repository.class ) , anyObject( AuthenticationInfo.class ), anyObject( ProxyInfo.class ) ); + } + catch ( ConnectionException e ) + { + fail( "This shouldn't happen!!" ); + } + catch ( AuthenticationException e ) + { + fail( "This shouldn't happen!!" ); + } + + try + { + wagon.get( anyString(), anyObject( File.class ) ); + } + catch ( TransferFailedException e ) + { + fail( "This shouldn't happen!!" ); + } + catch ( ResourceDoesNotExistException e ) + { + fail( "This shouldn't happen!!" ); + } + catch ( AuthorizationException e ) + { + fail( "This shouldn't happen!!" ); + } + + try + { + wagon.disconnect(); + expectLastCall().andThrow( error ); + } + catch ( ConnectionException e ) + { + fail( "This shouldn't happen!!" ); + } + } +} diff --git a/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/download/DownloadFailedExceptionTest.java b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/download/DownloadFailedExceptionTest.java new file mode 100644 index 000000000..a6c957c1f --- /dev/null +++ b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/download/DownloadFailedExceptionTest.java @@ -0,0 +1,44 @@ +package org.apache.maven.shared.io.download; + +/* + * 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. + */ + +import junit.framework.TestCase; + +public class DownloadFailedExceptionTest + extends TestCase +{ + + public void testShouldConstructWithUrlAndMessage() + { + new DownloadFailedException( "http://www.google.com", "can't find." ); + } + + public void testShouldConstructWithUrlMessageAndException() + { + new DownloadFailedException( "http://www.google.com", "can't find.", new NullPointerException() ); + } + + public void testShouldRetrieveUrlFromConstructor() + { + String url = "http://www.google.com"; + assertEquals( url, new DownloadFailedException( url, "can't find." ).getUrl() ); + } + +} diff --git a/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/ArtifactLocationTest.java b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/ArtifactLocationTest.java new file mode 100644 index 000000000..ff742dec5 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/ArtifactLocationTest.java @@ -0,0 +1,81 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.DefaultArtifact; +import org.apache.maven.artifact.handler.DefaultArtifactHandler; +import org.apache.maven.artifact.versioning.VersionRange; +import org.apache.maven.shared.io.Utils; + +public class ArtifactLocationTest + extends TestCase +{ + + public void testShouldConstructFromTempFileSpecification() + throws IOException + { + File f = File.createTempFile( "artifact-location.", ".test" ); + f.deleteOnExit(); + + Artifact a = new DefaultArtifact( "group", "artifact", VersionRange.createFromVersion( "1" ), null, "jar", + null, new DefaultArtifactHandler() ); + + a.setFile( f ); + + ArtifactLocation location = new ArtifactLocation( a, f.getAbsolutePath() ); + + assertSame( f, location.getFile() ); + } + + public void testShouldRead() + throws IOException + { + File f = File.createTempFile( "url-location.", ".test" ); + f.deleteOnExit(); + + String testStr = "This is a test"; + + Utils.writeFileWithEncoding( f, testStr, "US-ASCII" ); + + Artifact a = new DefaultArtifact( "group", "artifact", VersionRange.createFromVersion( "1" ), null, "jar", + null, new DefaultArtifactHandler() ); + + a.setFile( f ); + + ArtifactLocation location = new ArtifactLocation( a, f.getAbsolutePath() ); + + location.open(); + + byte[] buffer = new byte[testStr.length()]; + + int read = location.read( buffer ); + + assertEquals( testStr.length(), read ); + + assertEquals( testStr, new String( buffer, "US-ASCII" ) ); + } + +} diff --git a/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/ArtifactLocatorStrategyTest.java b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/ArtifactLocatorStrategyTest.java new file mode 100644 index 000000000..540797776 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/ArtifactLocatorStrategyTest.java @@ -0,0 +1,507 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import java.io.File; +import java.io.IOException; +import java.util.Collections; + +import junit.framework.TestCase; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.resolver.ArtifactNotFoundException; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; +import org.apache.maven.artifact.resolver.ArtifactResolver; +import org.apache.maven.shared.io.logging.DefaultMessageHolder; +import org.apache.maven.shared.io.logging.MessageHolder; + +import static org.easymock.EasyMock.*; + +public class ArtifactLocatorStrategyTest + extends TestCase +{ + + private ArtifactFactory factory; + + private ArtifactResolver resolver; + + private ArtifactRepository localRepository; + + public void setUp() + { + factory = createMock( ArtifactFactory.class ); + resolver = createMock( ArtifactResolver.class ); + localRepository = createMock( ArtifactRepository.class ); + } + + public void testShouldConstructWithoutDefaultArtifactType() + { + replay( factory, resolver, localRepository ); + + new ArtifactLocatorStrategy( factory, resolver, localRepository, Collections.EMPTY_LIST ); + + verify( factory, resolver, localRepository ); + } + + public void testShouldConstructWithDefaultArtifactType() + { + replay( factory, resolver, localRepository ); + + new ArtifactLocatorStrategy( factory, resolver, localRepository, Collections.EMPTY_LIST, "zip" ); + + verify( factory, resolver, localRepository ); + } + + public void testShouldFailToResolveSpecWithOneToken() + { + replay( factory, resolver, localRepository ); + + LocatorStrategy strategy = new ArtifactLocatorStrategy( factory, resolver, localRepository, + Collections.EMPTY_LIST, "zip" ); + MessageHolder mh = new DefaultMessageHolder(); + + Location location = strategy.resolve( "one-token", mh ); + + assertNull( location ); + assertEquals( 1, mh.size() ); + + verify( factory, resolver, localRepository ); + } + + public void testShouldFailToResolveSpecWithTwoTokens() + { + replay( factory, resolver, localRepository ); + + LocatorStrategy strategy = new ArtifactLocatorStrategy( factory, resolver, localRepository, + Collections.EMPTY_LIST, "zip" ); + MessageHolder mh = new DefaultMessageHolder(); + + Location location = strategy.resolve( "two:tokens", mh ); + + assertNull( location ); + assertEquals( 1, mh.size() ); + + verify( factory, resolver, localRepository ); + } + + public void testShouldResolveSpecWithThreeTokensUsingDefaultType() + throws IOException + { + File tempFile = File.createTempFile( "artifact-location.", ".temp" ); + tempFile.deleteOnExit(); + + Artifact artifact = createMock( Artifact.class ); + + expect( artifact.getFile() ).andReturn( tempFile ); + expect( artifact.getFile() ).andReturn( tempFile ); + + expect( factory.createArtifact( "group", "artifact", "version", null, "jar" ) ).andReturn( artifact ); + + try + { + resolver.resolve( artifact, Collections.emptyList(), localRepository ); + } + catch ( ArtifactResolutionException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + catch ( ArtifactNotFoundException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + + replay( factory, resolver, localRepository, artifact ); + + LocatorStrategy strategy = new ArtifactLocatorStrategy( factory, resolver, localRepository, + Collections.EMPTY_LIST ); + MessageHolder mh = new DefaultMessageHolder(); + + Location location = strategy.resolve( "group:artifact:version", mh ); + + assertNotNull( location ); + assertEquals( 0, mh.size() ); + + assertSame( tempFile, location.getFile() ); + + verify( factory, resolver, localRepository, artifact ); + } + + public void testShouldResolveSpecWithThreeTokensUsingCustomizedDefaultType() + throws IOException + { + File tempFile = File.createTempFile( "artifact-location.", ".temp" ); + tempFile.deleteOnExit(); + + Artifact artifact = createMock( Artifact.class ); + + expect( artifact.getFile() ).andReturn( tempFile ); + expect( artifact.getFile() ).andReturn( tempFile ); + + expect( factory.createArtifact( "group", "artifact", "version", null, "zip" ) ).andReturn( artifact ); + + try + { + resolver.resolve( artifact, Collections.emptyList(), localRepository ); + } + catch ( ArtifactResolutionException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + catch ( ArtifactNotFoundException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + + replay( factory, resolver, localRepository, artifact ); + + LocatorStrategy strategy = new ArtifactLocatorStrategy( factory, resolver, localRepository, + Collections.EMPTY_LIST, "zip" ); + MessageHolder mh = new DefaultMessageHolder(); + + Location location = strategy.resolve( "group:artifact:version", mh ); + + assertNotNull( location ); + assertEquals( 0, mh.size() ); + + assertSame( tempFile, location.getFile() ); + + verify( factory, resolver, localRepository, artifact ); + } + + public void testShouldResolveSpecWithFourTokens() + throws IOException + { + File tempFile = File.createTempFile( "artifact-location.", ".temp" ); + tempFile.deleteOnExit(); + + Artifact artifact = createMock( Artifact.class ); + + expect( artifact.getFile() ).andReturn( tempFile ); + expect( artifact.getFile() ).andReturn( tempFile ); + + expect( factory.createArtifact( "group", "artifact", "version", null, "zip" ) ).andReturn( artifact ); + + try + { + resolver.resolve( artifact, Collections.emptyList(), localRepository ); + } + catch ( ArtifactResolutionException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + catch ( ArtifactNotFoundException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + + replay( factory, resolver, localRepository, artifact ); + + LocatorStrategy strategy = new ArtifactLocatorStrategy( factory, resolver, localRepository, + Collections.EMPTY_LIST ); + MessageHolder mh = new DefaultMessageHolder(); + + Location location = strategy.resolve( "group:artifact:version:zip", mh ); + + assertNotNull( location ); + assertEquals( 0, mh.size() ); + + assertSame( tempFile, location.getFile() ); + + verify( factory, resolver, localRepository, artifact ); + } + + public void testShouldResolveSpecWithFiveTokens() + throws IOException + { + File tempFile = File.createTempFile( "artifact-location.", ".temp" ); + tempFile.deleteOnExit(); + + Artifact artifact = createMock( Artifact.class ); + + expect( artifact.getFile() ).andReturn( tempFile ); + expect( artifact.getFile() ).andReturn( tempFile ); + + expect( factory.createArtifactWithClassifier( "group", "artifact", "version", "zip", "classifier" ) ) + .andReturn( artifact ); + + try + { + resolver.resolve( artifact, Collections.emptyList(), localRepository ); + } + catch ( ArtifactResolutionException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + catch ( ArtifactNotFoundException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + + replay( factory, resolver, localRepository, artifact ); + + LocatorStrategy strategy = new ArtifactLocatorStrategy( factory, resolver, localRepository, + Collections.EMPTY_LIST ); + MessageHolder mh = new DefaultMessageHolder(); + + Location location = strategy.resolve( "group:artifact:version:zip:classifier", mh ); + + assertNotNull( location ); + assertEquals( 0, mh.size() ); + + assertSame( tempFile, location.getFile() ); + + verify( factory, resolver, localRepository, artifact ); + } + + public void testShouldResolveSpecWithFiveTokensAndEmptyTypeToken() + throws IOException + { + File tempFile = File.createTempFile( "artifact-location.", ".temp" ); + tempFile.deleteOnExit(); + + Artifact artifact = createMock( Artifact.class ); + + expect( artifact.getFile() ).andReturn( tempFile ); + expect( artifact.getFile() ).andReturn( tempFile ); + + expect( factory.createArtifactWithClassifier( "group", "artifact", "version", "jar", "classifier" ) ) + .andReturn( artifact ); + + try + { + resolver.resolve( artifact, Collections.emptyList(), localRepository ); + } + catch ( ArtifactResolutionException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + catch ( ArtifactNotFoundException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + + replay( factory, resolver, localRepository, artifact ); + + LocatorStrategy strategy = new ArtifactLocatorStrategy( factory, resolver, localRepository, + Collections.EMPTY_LIST ); + MessageHolder mh = new DefaultMessageHolder(); + + Location location = strategy.resolve( "group:artifact:version::classifier", mh ); + + assertNotNull( location ); + assertEquals( 0, mh.size() ); + + assertSame( tempFile, location.getFile() ); + + verify( factory, resolver, localRepository, artifact ); + } + + public void testShouldResolveSpecWithMoreThanFiveTokens() + throws IOException + { + File tempFile = File.createTempFile( "artifact-location.", ".temp" ); + tempFile.deleteOnExit(); + + Artifact artifact = createMock( Artifact.class ); + + expect( artifact.getFile() ).andReturn( tempFile ); + expect( artifact.getFile() ).andReturn( tempFile ); + + expect( factory.createArtifactWithClassifier( "group", "artifact", "version", "zip", "classifier" ) ) + .andReturn( artifact ); + + try + { + resolver.resolve( artifact, Collections.emptyList(), localRepository ); + } + catch ( ArtifactResolutionException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + catch ( ArtifactNotFoundException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + + replay( factory, resolver, localRepository, artifact ); + + LocatorStrategy strategy = new ArtifactLocatorStrategy( factory, resolver, localRepository, + Collections.EMPTY_LIST ); + MessageHolder mh = new DefaultMessageHolder(); + + Location location = strategy.resolve( "group:artifact:version:zip:classifier:six:seven", mh ); + + assertNotNull( location ); + assertEquals( 1, mh.size() ); + + assertTrue( mh.render().indexOf( ":six:seven" ) > -1 ); + + assertSame( tempFile, location.getFile() ); + + verify( factory, resolver, localRepository, artifact ); + } + + public void testShouldNotResolveSpecToArtifactWithNullFile() + throws IOException + { + Artifact artifact = createMock( Artifact.class ); + + expect( artifact.getFile() ).andReturn( null ); + expect( artifact.getId() ).andReturn( "" ); + + expect( factory.createArtifact( "group", "artifact", "version", null, "jar" )).andReturn( artifact ); + + try + { + resolver.resolve( artifact, Collections.emptyList(), localRepository ); + } + catch ( ArtifactResolutionException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + catch ( ArtifactNotFoundException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + + replay( factory, resolver, localRepository, artifact ); + + LocatorStrategy strategy = new ArtifactLocatorStrategy( factory, resolver, localRepository, + Collections.EMPTY_LIST ); + MessageHolder mh = new DefaultMessageHolder(); + + Location location = strategy.resolve( "group:artifact:version", mh ); + + assertNull( location ); + assertEquals( 1, mh.size() ); + + assertTrue( mh.render().indexOf( "" ) > -1 ); + + verify( factory, resolver, localRepository, artifact ); + } + + public void testShouldNotResolveWhenArtifactNotFoundExceptionThrown() + throws IOException + { + Artifact artifact = createMock( Artifact.class ); + + expect( artifact.getId() ).andReturn( "" ); + + expect( factory.createArtifact( "group", "artifact", "version", null, "jar" ) ).andReturn( artifact ); + + try + { + resolver.resolve( artifact, Collections.emptyList(), localRepository ); + expectLastCall().andThrow( new ArtifactNotFoundException( "not found", "group", "artifact", "version", + "jar", null, Collections.emptyList(), + "http://nowhere.com", Collections.emptyList(), + new NullPointerException() ) ); + } + catch ( ArtifactResolutionException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + catch ( ArtifactNotFoundException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + + replay( factory, resolver, localRepository, artifact ); + + LocatorStrategy strategy = new ArtifactLocatorStrategy( factory, resolver, localRepository, + Collections.EMPTY_LIST ); + MessageHolder mh = new DefaultMessageHolder(); + + Location location = strategy.resolve( "group:artifact:version", mh ); + + assertNull( location ); + assertEquals( 1, mh.size() ); + + assertTrue( mh.render().indexOf( "" ) > -1 ); + assertTrue( mh.render().indexOf( "not found" ) > -1 ); + + verify( factory, resolver, localRepository, artifact ); + } + + public void testShouldNotResolveWhenArtifactResolutionExceptionThrown() + throws IOException + { + Artifact artifact = createMock( Artifact.class ); + + expect( artifact.getId() ).andReturn( "" ); + + expect( factory.createArtifact( "group", "artifact", "version", null, "jar" ) ).andReturn( artifact ); + + try + { + resolver.resolve( artifact, Collections.emptyList(), localRepository ); + expectLastCall().andThrow( new ArtifactResolutionException( "resolution failed", "group", "artifact", + "version", "jar", null, Collections.emptyList(), + Collections.emptyList(), + new NullPointerException() ) ); + + } + catch ( ArtifactResolutionException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + catch ( ArtifactNotFoundException e ) + { + // should never happen + fail( "This should NEVER happen. It's a mock!" ); + } + + replay( factory, resolver, localRepository, artifact ); + + LocatorStrategy strategy = new ArtifactLocatorStrategy( factory, resolver, localRepository, + Collections.EMPTY_LIST ); + MessageHolder mh = new DefaultMessageHolder(); + + Location location = strategy.resolve( "group:artifact:version", mh ); + + assertNull( location ); + assertEquals( 1, mh.size() ); + + assertTrue( mh.render().indexOf( "" ) > -1 ); + assertTrue( mh.render().indexOf( "resolution failed" ) > -1 ); + + verify( factory, resolver, localRepository, artifact ); + } + +} diff --git a/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/ClasspathResourceLocatorStrategyTest.java b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/ClasspathResourceLocatorStrategyTest.java new file mode 100644 index 000000000..e4cd734c8 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/ClasspathResourceLocatorStrategyTest.java @@ -0,0 +1,59 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import org.apache.maven.shared.io.logging.DefaultMessageHolder; +import org.apache.maven.shared.io.logging.MessageHolder; + +import junit.framework.TestCase; + +public class ClasspathResourceLocatorStrategyTest + extends TestCase +{ + + public void testShouldConstructWithNoParams() + { + new ClasspathResourceLocatorStrategy(); + } + + public void testShouldConstructWithTempFileOptions() + { + new ClasspathResourceLocatorStrategy( "prefix.", ".suffix", true ); + } + + public void testShouldFailToResolveMissingClasspathResource() + { + MessageHolder mh = new DefaultMessageHolder(); + Location location = new ClasspathResourceLocatorStrategy().resolve( "/some/missing/path", mh ); + + assertNull( location ); + assertEquals( 1, mh.size() ); + } + + public void testShouldResolveExistingClasspathResourceWithoutPrecedingSlash() + { + MessageHolder mh = new DefaultMessageHolder(); + Location location = new ClasspathResourceLocatorStrategy().resolve( "META-INF/maven/test.properties", mh ); + + assertNotNull( location ); + assertEquals( 0, mh.size() ); + } + +} diff --git a/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/FileLocationTest.java b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/FileLocationTest.java new file mode 100644 index 000000000..467833a41 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/FileLocationTest.java @@ -0,0 +1,180 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import org.apache.maven.shared.io.Utils; +import org.apache.maven.shared.utils.io.IOUtil; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; + +import junit.framework.TestCase; + +public class FileLocationTest + extends TestCase +{ + + public void testShouldConstructWithFileThenRetrieveSameFile() throws IOException + { + File file = File.createTempFile( "test.", ".file-location" ); + file.deleteOnExit(); + + FileLocation location = new FileLocation( file, file.getAbsolutePath() ); + + assertSame( file, location.getFile() ); + assertEquals( file.getAbsolutePath(), location.getSpecification() ); + } + + public void testShouldReadFileContentsUsingByteBuffer() throws IOException + { + File file = File.createTempFile( "test.", ".file-location" ); + file.deleteOnExit(); + + String testStr = "This is a test"; + + Utils.writeFileWithEncoding( file, testStr, "US-ASCII" ); + + FileLocation location = new FileLocation( file, file.getAbsolutePath() ); + + location.open(); + + ByteBuffer buffer = ByteBuffer.allocate( testStr.length() ); + location.read( buffer ); + + assertEquals( testStr, new String( buffer.array(), "US-ASCII" ) ); + } + + public void testShouldReadFileContentsUsingStream() throws IOException + { + File file = File.createTempFile( "test.", ".file-location" ); + file.deleteOnExit(); + + String testStr = "This is a test"; + + Utils.writeFileWithEncoding( file, testStr, "US-ASCII" ); + + FileLocation location = new FileLocation( file, file.getAbsolutePath() ); + + location.open(); + + try ( InputStream stream = location.getInputStream() ) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + IOUtil.copy( stream, out ); + + assertEquals( testStr, new String(out.toByteArray(), "US-ASCII" ) ); + } + } + + public void testShouldReadFileContentsUsingByteArray() throws IOException + { + File file = File.createTempFile( "test.", ".file-location" ); + file.deleteOnExit(); + + String testStr = "This is a test"; + + Utils.writeFileWithEncoding( file, testStr, "US-ASCII" ); + + FileLocation location = new FileLocation( file, file.getAbsolutePath() ); + + location.open(); + + byte[] buffer = new byte[ testStr.length() ]; + location.read( buffer ); + + assertEquals( testStr, new String( buffer, "US-ASCII" ) ); + } + + public void testShouldReadThenClose() throws IOException + { + File file = File.createTempFile( "test.", ".file-location" ); + file.deleteOnExit(); + + String testStr = "This is a test"; + + Utils.writeFileWithEncoding( file, testStr, "US-ASCII" ); + + FileLocation location = new FileLocation( file, file.getAbsolutePath() ); + + location.open(); + + byte[] buffer = new byte[ testStr.length() ]; + location.read( buffer ); + + assertEquals( testStr, new String( buffer, "US-ASCII" ) ); + + location.close(); + } + + public void testShouldOpenThenFailToSetFile() throws IOException + { + File file = File.createTempFile( "test.", ".file-location" ); + file.deleteOnExit(); + + TestFileLocation location = new TestFileLocation( file.getAbsolutePath() ); + + location.open(); + + try + { + location.setFile( file ); + + fail( "should not succeed." ); + } + catch( IllegalStateException e ) + { + } + } + + public void testShouldConstructWithoutFileThenSetFileThenOpen() throws IOException + { + File file = File.createTempFile( "test.", ".file-location" ); + file.deleteOnExit(); + + TestFileLocation location = new TestFileLocation( file.getAbsolutePath() ); + + location.setFile( file ); + location.open(); + } + + public void testShouldConstructWithLocationThenRetrieveEquivalentFile() throws IOException + { + File file = File.createTempFile( "test.", ".file-location" ); + file.deleteOnExit(); + + Location location = new TestFileLocation( file.getAbsolutePath() ); + + assertEquals( file, location.getFile() ); + assertEquals( file.getAbsolutePath(), location.getSpecification() ); + } + + private static final class TestFileLocation extends FileLocation + { + + TestFileLocation( String specification ) + { + super( specification ); + } + + } + +} diff --git a/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/FileLocatorStrategyTest.java b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/FileLocatorStrategyTest.java new file mode 100644 index 000000000..96a899d83 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/FileLocatorStrategyTest.java @@ -0,0 +1,70 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import java.io.File; +import java.io.IOException; + +import org.apache.maven.shared.io.logging.DefaultMessageHolder; +import org.apache.maven.shared.io.logging.MessageHolder; + +import junit.framework.TestCase; + +public class FileLocatorStrategyTest + extends TestCase +{ + + public void testShouldResolveExistingTempFileLocation() throws IOException + { + File f = File.createTempFile( "file-locator.", ".test" ); + f.deleteOnExit(); + + FileLocatorStrategy fls = new FileLocatorStrategy(); + + MessageHolder mh = new DefaultMessageHolder(); + + Location location = fls.resolve( f.getAbsolutePath(), mh ); + + assertNotNull( location ); + + assertTrue( mh.isEmpty() ); + + assertEquals( f, location.getFile() ); + } + + public void testShouldFailToResolveNonExistentFileLocation() throws IOException + { + File f = File.createTempFile( "file-locator.", ".test" ); + f.delete(); + + FileLocatorStrategy fls = new FileLocatorStrategy(); + + MessageHolder mh = new DefaultMessageHolder(); + + Location location = fls.resolve( f.getAbsolutePath(), mh ); + + assertNull( location ); + + System.out.println( mh.render() ); + + assertEquals( 1, mh.size() ); + } + +} diff --git a/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/LocatorTest.java b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/LocatorTest.java new file mode 100644 index 000000000..ab976ecc8 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/LocatorTest.java @@ -0,0 +1,138 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.maven.shared.io.logging.DefaultMessageHolder; +import org.apache.maven.shared.io.logging.MessageHolder; + +import junit.framework.TestCase; + +import static org.easymock.EasyMock.*; + +public class LocatorTest + extends TestCase +{ + + public void testShouldConstructWithNoParams() + { + new Locator(); + } + + public void testShouldConstructWithStrategyStackAndMessageHolder() + { + new Locator( Collections.emptyList(), new DefaultMessageHolder() ); + } + + public void testShouldAllowModificationOfStrategiesAfterConstructionWithUnmodifiableStack() + { + Locator locator = new Locator( Collections.unmodifiableList( Collections.emptyList() ), + new DefaultMessageHolder() ); + + locator.addStrategy( new FileLocatorStrategy() ); + + assertEquals( 1, locator.getStrategies().size() ); + } + + public void testShouldRetrieveNonNullMessageHolderWhenConstructedWithoutParams() + { + assertNotNull( new Locator().getMessageHolder() ); + } + + public void testSetStrategiesShouldClearAnyPreExistingStrategiesOut() + { + LocatorStrategy originalStrategy = createMock( LocatorStrategy.class ); + LocatorStrategy replacementStrategy = createMock( LocatorStrategy.class ); + + replay( originalStrategy, replacementStrategy ); + + Locator locator = new Locator(); + locator.addStrategy( originalStrategy ); + + locator.setStrategies( Collections.singletonList( replacementStrategy ) ); + + List strategies = locator.getStrategies(); + + assertFalse( strategies.contains( originalStrategy ) ); + assertTrue( strategies.contains( replacementStrategy ) ); + + verify( originalStrategy, replacementStrategy ); + } + + public void testShouldRemovePreviouslyAddedStrategy() + { + LocatorStrategy originalStrategy = createMock( LocatorStrategy.class ); + + replay( originalStrategy ); + + Locator locator = new Locator(); + locator.addStrategy( originalStrategy ); + + List strategies = locator.getStrategies(); + + assertTrue( strategies.contains( originalStrategy ) ); + + locator.removeStrategy( originalStrategy ); + + strategies = locator.getStrategies(); + + assertFalse( strategies.contains( originalStrategy ) ); + + verify( originalStrategy ); + } + + public void testResolutionFallsThroughStrategyStackAndReturnsNullIfNotResolved() + { + List strategies = new ArrayList(); + + strategies.add( new LoggingLocatorStrategy() ); + strategies.add( new LoggingLocatorStrategy() ); + strategies.add( new LoggingLocatorStrategy() ); + + MessageHolder mh = new DefaultMessageHolder(); + + Locator locator = new Locator( strategies, mh ); + + Location location = locator.resolve( "some-specification" ); + + assertNull( location ); + + assertEquals( 3, mh.size() ); + } + + public static final class LoggingLocatorStrategy implements LocatorStrategy + { + + static int instanceCounter = 0; + + int counter = instanceCounter++; + + public Location resolve( String locationSpecification, MessageHolder messageHolder ) + { + messageHolder.addMessage( "resolve hit on strategy-" + (counter) ); + return null; + } + + } + +} diff --git a/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/URLLocationTest.java b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/URLLocationTest.java new file mode 100644 index 000000000..f63321a74 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/URLLocationTest.java @@ -0,0 +1,81 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import java.io.File; +import java.io.IOException; +import java.net.URL; + +import org.apache.maven.shared.io.Utils; + +import junit.framework.TestCase; + +public class URLLocationTest + extends TestCase +{ + + public void testShouldConstructFromUrlAndTempFileSpecifications() throws IOException + { + File f = File.createTempFile( "url-location.", ".test" ); + f.deleteOnExit(); + + URL url = f.toURL(); + + new URLLocation( url, f.getAbsolutePath(), "prefix.", ".suffix", true ); + } + + public void testShouldTransferFromTempFile() throws IOException + { + File f = File.createTempFile( "url-location.", ".test" ); + f.deleteOnExit(); + + URL url = f.toURL(); + + URLLocation location = new URLLocation( url, f.getAbsolutePath(), "prefix.", ".suffix", true ); + + assertNotNull( location.getFile() ); + assertFalse( f.equals( location.getFile() ) ); + } + + public void testShouldTransferFromTempFileThenRead() throws IOException + { + File f = File.createTempFile( "url-location.", ".test" ); + f.deleteOnExit(); + + String testStr = "This is a test"; + + Utils.writeFileWithEncoding( f, testStr, "US-ASCII" ); + + URL url = f.toURL(); + + URLLocation location = new URLLocation( url, f.getAbsolutePath(), "prefix.", ".suffix", true ); + + location.open(); + + byte[] buffer = new byte[ testStr.length() ]; + + int read = location.read( buffer ); + + assertEquals( testStr.length(), read ); + + assertEquals( testStr, new String( buffer, "US-ASCII" ) ); + } + +} diff --git a/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/URLLocatorStrategyTest.java b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/URLLocatorStrategyTest.java new file mode 100644 index 000000000..210cfe5a7 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/location/URLLocatorStrategyTest.java @@ -0,0 +1,79 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import java.io.File; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.apache.maven.shared.io.Utils; +import org.apache.maven.shared.io.logging.DefaultMessageHolder; +import org.apache.maven.shared.io.logging.MessageHolder; + +public class URLLocatorStrategyTest + extends TestCase +{ + + public void testShouldConstructWithNoParams() + { + new URLLocatorStrategy(); + } + + public void testShouldConstructWithTempFileOptions() + { + new URLLocatorStrategy( "prefix.", ".suffix", true ); + } + + public void testShouldFailToResolveWithMalformedUrl() + { + MessageHolder mh = new DefaultMessageHolder(); + + Location location = new URLLocatorStrategy().resolve( "://www.google.com", mh ); + + assertNull( location ); + assertEquals( 1, mh.size() ); + } + + public void testShouldResolveUrlForTempFile() throws IOException + { + File tempFile = File.createTempFile( "prefix.", ".suffix" ); + tempFile.deleteOnExit(); + + String testStr = "This is a test."; + + Utils.writeFileWithEncoding( tempFile, testStr, "US-ASCII" ); + + MessageHolder mh = new DefaultMessageHolder(); + + Location location = new URLLocatorStrategy().resolve( tempFile.toURL().toExternalForm(), mh ); + + assertNotNull( location ); + assertEquals( 0, mh.size() ); + + location.open(); + + byte[] buffer = new byte[testStr.length()]; + location.read( buffer ); + + assertEquals( testStr, new String( buffer, "US-ASCII" ) ); + } + +} diff --git a/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/logging/DefaultMessageHolderTest.java b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/logging/DefaultMessageHolderTest.java new file mode 100644 index 000000000..ea3b80565 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/logging/DefaultMessageHolderTest.java @@ -0,0 +1,304 @@ +package org.apache.maven.shared.io.logging; + +/* + * 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. + */ + +import java.io.PrintWriter; +import java.io.StringWriter; + +import junit.framework.TestCase; + +public class DefaultMessageHolderTest + extends TestCase +{ + + // MessageHolder newMessage(); + // int size(); + // String render(); + public void testNewMessageIncrementsSizeWhenEmpty() + { + MessageHolder mh = new DefaultMessageHolder(); + + assertEquals( 0, mh.size() ); + + MessageHolder test = mh.newMessage(); + + assertSame( mh, test ); + + assertEquals( 1, mh.size() ); + + assertEquals( "", mh.render() ); + } + + // MessageHolder append( CharSequence messagePart ); + // int size(); + // String render(); + public void testAppendCreatesNewMessageIfNoneCurrent() + { + MessageHolder mh = new DefaultMessageHolder(); + + assertEquals( 0, mh.size() ); + + MessageHolder test = mh.append( "test" ); + + assertSame( mh, test ); + + assertEquals( 1, mh.size() ); + + assertEquals( "[1] [INFO] test", mh.render() ); + } + + // MessageHolder append( Throwable error ); + // int size(); + // String render(); + public void testAppendErrorCreatesNewMessageIfNoneCurrent() + { + MessageHolder mh = new DefaultMessageHolder(); + + assertEquals( 0, mh.size() ); + + NullPointerException npe = new NullPointerException(); + + MessageHolder test = mh.append( npe ); + + assertSame( mh, test ); + + assertEquals( 1, mh.size() ); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter( sw ); + + npe.printStackTrace( pw ); + + assertEquals( "[1] [INFO] Error:\n" + sw.toString(), mh.render() ); + } + + // MessageHolder newMessage(); + // MessageHolder append( CharSequence messagePart ); + // int size(); + // String render(); + public void testNewMessageThenAppendOnlyIncrementsSizeByOne() + { + MessageHolder mh = new DefaultMessageHolder(); + + assertEquals( 0, mh.size() ); + + MessageHolder test = mh.newMessage(); + + assertSame( mh, test ); + + test = mh.append( "test" ); + + assertSame( mh, test ); + + assertEquals( 1, mh.size() ); + + assertEquals( "[1] [INFO] test", mh.render() ); + } + + // MessageHolder newMessage(); + // MessageHolder append( CharSequence messagePart ); + // MessageHolder append( CharSequence messagePart ); + // int size(); + // String render(); + public void testNewMessageThenAppendTwiceOnlyIncrementsSizeByOne() + { + MessageHolder mh = new DefaultMessageHolder(); + + assertEquals( 0, mh.size() ); + + MessageHolder test = mh.newMessage(); + + assertSame( mh, test ); + + test = mh.append( "test" ); + + assertSame( mh, test ); + + test = mh.append( " again" ); + + assertSame( mh, test ); + + assertEquals( 1, mh.size() ); + + assertEquals( "[1] [INFO] test again", mh.render() ); + } + + // MessageHolder newMessage(); + // MessageHolder append( CharSequence messagePart ); + // MessageHolder append( Throwable error ); + // int size(); + // String render(); + public void testNewMessageThenAppendBothMessageAndErrorOnlyIncrementsSizeByOne() + { + MessageHolder mh = new DefaultMessageHolder(); + + assertEquals( 0, mh.size() ); + + MessageHolder test = mh.newMessage(); + + assertSame( mh, test ); + + test = mh.append( "test" ); + + assertSame( mh, test ); + + NullPointerException npe = new NullPointerException(); + + test = mh.append( npe ); + + assertSame( mh, test ); + + assertEquals( 1, mh.size() ); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter( sw ); + + npe.printStackTrace( pw ); + + assertEquals( "[1] [INFO] test\nError:\n" + sw.toString(), mh.render() ); + } + + // MessageHolder addMessage( CharSequence messagePart ); + // int size(); + // String render(); + public void testAddMessageIncrementsSizeByOne() + { + MessageHolder mh = new DefaultMessageHolder(); + MessageHolder check = mh.addMessage( "test" ); + + assertSame( mh, check ); + + assertEquals( 1, mh.size() ); + assertEquals( "[1] [INFO] test", mh.render() ); + } + + // MessageHolder addMessage( CharSequence messagePart ); + // int size(); + // String render(); + public void testAddMessageTwiceIncrementsSizeByTwo() + { + MessageHolder mh = new DefaultMessageHolder(); + MessageHolder check = mh.addMessage( "test" ); + + assertSame( mh, check ); + + check = mh.addMessage( "test2" ); + + assertSame( mh, check ); + + assertEquals( 2, mh.size() ); + assertEquals( "[1] [INFO] test\n\n[2] [INFO] test2", mh.render() ); + } + + // MessageHolder addMessage( CharSequence messagePart, Throwable error ); + // int size(); + // String render(); + public void testAddMessageWithErrorIncrementsSizeByOne() + { + MessageHolder mh = new DefaultMessageHolder(); + + NullPointerException npe = new NullPointerException(); + + MessageHolder check = mh.addMessage( "test", npe ); + + assertSame( mh, check ); + + assertEquals( 1, mh.size() ); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter( sw ); + + npe.printStackTrace( pw ); + + assertEquals( "[1] [INFO] test\nError:\n" + sw.toString(), mh.render() ); + } + + // MessageHolder addMessage( CharSequence messagePart, Throwable error ); + // MessageHolder addMessage( CharSequence messagePart ); + // int size(); + // String render(); + public void testAddMessageWithErrorThenWithJustMessageIncrementsSizeByTwo() + { + MessageHolder mh = new DefaultMessageHolder(); + + NullPointerException npe = new NullPointerException(); + + MessageHolder check = mh.addMessage( "test", npe ); + + assertSame( mh, check ); + + check = mh.addMessage( "test2" ); + + assertSame( mh, check ); + + assertEquals( 2, mh.size() ); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter( sw ); + + npe.printStackTrace( pw ); + + assertEquals( "[1] [INFO] test\nError:\n" + sw.toString() + "\n\n[2] [INFO] test2", mh.render() ); + } + + // MessageHolder addMessage( Throwable error ); + // int size(); + // String render(); + public void testAddMessageWithJustErrorIncrementsSizeByOne() + { + MessageHolder mh = new DefaultMessageHolder(); + + NullPointerException npe = new NullPointerException(); + + MessageHolder check = mh.addMessage( npe ); + + assertSame( mh, check ); + + assertEquals( 1, mh.size() ); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter( sw ); + + npe.printStackTrace( pw ); + + assertEquals( "[1] [INFO] Error:\n" + sw.toString(), mh.render() ); + } + + // boolean isEmpty(); + public void testIsEmptyAfterConstruction() + { + assertTrue( new DefaultMessageHolder().isEmpty() ); + } + + // boolean isEmpty(); + public void testIsNotEmptyAfterConstructionAndNewMessageCall() + { + assertFalse( new DefaultMessageHolder().newMessage().isEmpty() ); + } + + public void testAppendCharSequence() + { + MessageHolder mh = new DefaultMessageHolder(); + mh.newMessage().append( new StringBuffer( "This is a test" ) ); + + assertTrue( mh.render().indexOf( "This is a test" ) > -1 ); + } + +} diff --git a/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/scan/mapping/SuffixMappingTest.java b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/scan/mapping/SuffixMappingTest.java new file mode 100644 index 000000000..197aad6c2 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/test/java/org/apache/maven/shared/io/scan/mapping/SuffixMappingTest.java @@ -0,0 +1,130 @@ +package org.apache.maven.shared.io.scan.mapping; + +/* + * 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. + */ + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.HashSet; +import java.util.Set; + +import org.apache.maven.shared.io.scan.InclusionScanException; +import org.junit.Test; + +/** + * @author jdcasey + */ +public class SuffixMappingTest +{ + @Test + public void testShouldReturnSingleClassFileForSingleJavaFile() + throws InclusionScanException + { + String base = "path/to/file"; + + File basedir = new File( "." ); + + System.out.println( "basedir:" + basedir.getAbsolutePath() ); + SuffixMapping mapping = new SuffixMapping( ".java", ".class" ); + + Set results = mapping.getTargetFiles( basedir, base + ".java" ); + + assertEquals( "Returned wrong number of target files.", 1, results.size() ); + + assertEquals( "Target file is wrong.", new File( basedir, base + ".class" ), results.iterator().next() ); + } + + @Test + public void testShouldNotReturnClassFileWhenSourceFileHasWrongSuffix() + throws InclusionScanException + { + String base = "path/to/file"; + + File basedir = new File( "." ); + + SuffixMapping mapping = new SuffixMapping( ".java", ".class" ); + + Set results = mapping.getTargetFiles( basedir, base + ".xml" ); + + assertTrue( "Returned wrong number of target files.", results.isEmpty() ); + } + + @Test + public void testShouldReturnOneClassFileAndOneXmlFileForSingleJavaFile() + throws InclusionScanException + { + String base = "path/to/file"; + + File basedir = new File( "." ); + + Set targets = new HashSet(); + targets.add( ".class" ); + targets.add( ".xml" ); + + SuffixMapping mapping = new SuffixMapping( ".java", targets ); + + Set results = mapping.getTargetFiles( basedir, base + ".java" ); + + assertEquals( "Returned wrong number of target files.", 2, results.size() ); + + assertTrue( "Targets do not contain class target.", results.contains( new File( basedir, base + ".class" ) ) ); + + assertTrue( "Targets do not contain class target.", results.contains( new File( basedir, base + ".xml" ) ) ); + } + + @Test + public void testShouldReturnNoTargetFilesWhenSourceFileHasWrongSuffix() + throws InclusionScanException + { + String base = "path/to/file"; + + File basedir = new File( "." ); + + Set targets = new HashSet(); + targets.add( ".class" ); + targets.add( ".xml" ); + + SuffixMapping mapping = new SuffixMapping( ".java", targets ); + + Set results = mapping.getTargetFiles( basedir, base + ".apt" ); + + assertTrue( "Returned wrong number of target files.", results.isEmpty() ); + } + + @Test + public void testSingleTargetMapper() + throws InclusionScanException + { + String base = "path/to/file"; + + File basedir = new File( "target/" ); + + SingleTargetMapping mapping = new SingleTargetMapping( ".cs", "/foo" ); + + Set results = mapping.getTargetFiles( basedir, base + ".apt" ); + + assertTrue( results.isEmpty() ); + + results = mapping.getTargetFiles( basedir, base + ".cs" ); + + assertEquals( 1, results.size() ); + } +} diff --git a/Java-base/maven-shared-io/src/src/test/resources/META-INF/maven/test.properties b/Java-base/maven-shared-io/src/src/test/resources/META-INF/maven/test.properties new file mode 100644 index 000000000..379c6dbf2 --- /dev/null +++ b/Java-base/maven-shared-io/src/src/test/resources/META-INF/maven/test.properties @@ -0,0 +1,17 @@ +# 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. +test=successful From c5cb15a4dcc0e4fbcf65f2f70ddb3659fe0de06d Mon Sep 17 00:00:00 2001 From: Henry Lee Date: Thu, 30 Nov 2023 20:29:45 +0900 Subject: [PATCH 2/3] refactor(java): add maven-shared-io --- .../Dockerfile | 18 + .../buggy.java | 169 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 75 +++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 611 ++++++++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + 12 files changed, 993 insertions(+) create mode 100644 Java/maven-shared-io-ArtifactLocatorStrategy_150/Dockerfile create mode 100644 Java/maven-shared-io-ArtifactLocatorStrategy_150/buggy.java create mode 100644 Java/maven-shared-io-ArtifactLocatorStrategy_150/metadata.json create mode 100644 Java/maven-shared-io-ArtifactLocatorStrategy_150/npe.json create mode 100644 Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/Dockerfile create mode 100644 Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/buggy.java create mode 100644 Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/metadata.json create mode 100644 Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/npe.json create mode 100644 Java/maven-shared-io-DefaultMessageHolder_293/Dockerfile create mode 100644 Java/maven-shared-io-DefaultMessageHolder_293/buggy.java create mode 100644 Java/maven-shared-io-DefaultMessageHolder_293/metadata.json create mode 100644 Java/maven-shared-io-DefaultMessageHolder_293/npe.json diff --git a/Java/maven-shared-io-ArtifactLocatorStrategy_150/Dockerfile b/Java/maven-shared-io-ArtifactLocatorStrategy_150/Dockerfile new file mode 100644 index 000000000..4cf68844e --- /dev/null +++ b/Java/maven-shared-io-ArtifactLocatorStrategy_150/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-shared-io + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-shared-io-ArtifactLocatorStrategy_150/buggy.java b/Java/maven-shared-io-ArtifactLocatorStrategy_150/buggy.java new file mode 100644 index 000000000..8d32c3f31 --- /dev/null +++ b/Java/maven-shared-io-ArtifactLocatorStrategy_150/buggy.java @@ -0,0 +1,169 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import java.util.List; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.resolver.ArtifactNotFoundException; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; +import org.apache.maven.artifact.resolver.ArtifactResolver; +import org.apache.maven.shared.io.logging.MessageHolder; + +/** + * The locator strategy. + * + */ +public class ArtifactLocatorStrategy + implements LocatorStrategy +{ + private final ArtifactFactory factory; + + private final ArtifactResolver resolver; + + private String defaultArtifactType = "jar"; + + private final ArtifactRepository localRepository; + + private final List remoteRepositories; + + private String defaultClassifier = null; + + /** + * @param factory {@link ArtifactFactory} + * @param resolver {@link ArtifactResolver} + * @param localRepository {@link ArtifactRepository} + * @param remoteRepositories {@link ArtifactRepository} + */ + public ArtifactLocatorStrategy( ArtifactFactory factory, ArtifactResolver resolver, + ArtifactRepository localRepository, List remoteRepositories ) + { + this.factory = factory; + this.resolver = resolver; + this.localRepository = localRepository; + this.remoteRepositories = remoteRepositories; + } + + /** + * @param factory {@link ArtifactFactory} + * @param resolver {@link ArtifactResolver} + * @param localRepository {@link ArtifactRepository} + * @param remoteRepositories {@link ArtifactRepository} + * @param defaultArtifactType default artifact type. + */ + public ArtifactLocatorStrategy( ArtifactFactory factory, ArtifactResolver resolver, + ArtifactRepository localRepository, List remoteRepositories, + String defaultArtifactType ) + { + this.factory = factory; + this.resolver = resolver; + this.localRepository = localRepository; + this.remoteRepositories = remoteRepositories; + this.defaultArtifactType = defaultArtifactType; + } + + /** + * @param factory {@link ArtifactFactory} + * @param resolver {@link ArtifactResolver} + * @param localRepository {@link ArtifactRepository} + * @param remoteRepositories {@link ArtifactRepository} + * @param defaultArtifactType default artifact type. + * @param defaultClassifier default classifier. + */ + public ArtifactLocatorStrategy( ArtifactFactory factory, ArtifactResolver resolver, + ArtifactRepository localRepository, List remoteRepositories, + String defaultArtifactType, String defaultClassifier ) + { + this.factory = factory; + this.resolver = resolver; + this.localRepository = localRepository; + this.remoteRepositories = remoteRepositories; + this.defaultArtifactType = defaultArtifactType; + this.defaultClassifier = defaultClassifier; + } + + /** + * Assumes artifact identity is given in a set of comma-delimited tokens of + * the form: groupId:artifactId:version:type:classifier, where + * type and classifier are optional. + * @param locationSpecification location spec. + * @param messageHolder {@link MessageHolder} + * @return location. + */ +/** + * Assumes artifact identity is given in a set of comma-delimited tokens of + * the form: groupId:artifactId:version:type:classifier, where + * type and classifier are optional. + * + * @param locationSpecification + * location spec. + * @param messageHolder + * {@link MessageHolder} + * @return location. + */ +public org.apache.maven.shared.io.location.Location resolve(java.lang.String locationSpecification, org.apache.maven.shared.io.logging.MessageHolder messageHolder) { + java.lang.String[] parts = locationSpecification.split(":"); + org.apache.maven.shared.io.location.Location location = null; + if (parts.length > 2) { + java.lang.String groupId = parts[0]; + java.lang.String artifactId = parts[1]; + java.lang.String version = parts[2]; + java.lang.String type = defaultArtifactType; + if (parts.length > 3) { + if (parts[3].trim().length() > 0) { + type = parts[3]; + } + } + java.lang.String classifier = defaultClassifier; + if (parts.length > 4) { + classifier = parts[4]; + } + if (parts.length > 5) { + messageHolder.newMessage().append("Location specification has unused tokens: \'"); + for (int i = 5; i < parts.length; i++) { + messageHolder.append(":" + parts[i]); + } + } + org.apache.maven.artifact.Artifact artifact; + { + artifact = factory.createArtifactWithClassifier(groupId, artifactId, version, type, /* NPEX_NULL_EXP */ + classifier); + } + try { + resolver.resolve(artifact, remoteRepositories, localRepository); + if (artifact.getFile() != null) { + location = new org.apache.maven.shared.io.location.ArtifactLocation(artifact, locationSpecification); + } else { + messageHolder.addMessage(("Supposedly resolved artifact: " + artifact.getId()) + " does not have an associated file."); + } + } catch (org.apache.maven.artifact.resolver.ArtifactResolutionException e) { + messageHolder.addMessage((("Failed to resolve artifact: " + artifact.getId()) + " for location: ") + locationSpecification, e); + } catch (org.apache.maven.artifact.resolver.ArtifactNotFoundException e) { + messageHolder.addMessage((("Failed to resolve artifact: " + artifact.getId()) + " for location: ") + locationSpecification, e); + } + } else { + messageHolder.addMessage(("Invalid artifact specification: \'" + locationSpecification) + "\'. Must contain at least three fields, separated by \':\'."); + } + return location; +} + +} diff --git a/Java/maven-shared-io-ArtifactLocatorStrategy_150/metadata.json b/Java/maven-shared-io-ArtifactLocatorStrategy_150/metadata.json new file mode 100644 index 000000000..860aa3b6a --- /dev/null +++ b/Java/maven-shared-io-ArtifactLocatorStrategy_150/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-shared-io-ArtifactLocatorStrategy_150", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "src/main/java/org/apache/maven/shared/io/location/ArtifactLocatorStrategy.java", + "line": 149, + "npe_method": "resolve", + "deref_field": "classifier", + "npe_class": "ArtifactLocatorStrategy", + "repo": "maven-shared-io", + "bug_id": "ArtifactLocatorStrategy_150" + } +} diff --git a/Java/maven-shared-io-ArtifactLocatorStrategy_150/npe.json b/Java/maven-shared-io-ArtifactLocatorStrategy_150/npe.json new file mode 100644 index 000000000..88c27f608 --- /dev/null +++ b/Java/maven-shared-io-ArtifactLocatorStrategy_150/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/maven/shared/io/location/ArtifactLocatorStrategy.java", + "line": 149, + "npe_method": "resolve", + "deref_field": "classifier", + "npe_class": "ArtifactLocatorStrategy" +} \ No newline at end of file diff --git a/Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/Dockerfile b/Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/Dockerfile new file mode 100644 index 000000000..4cf68844e --- /dev/null +++ b/Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-shared-io + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/buggy.java b/Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/buggy.java new file mode 100644 index 000000000..a995ad0a0 --- /dev/null +++ b/Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/buggy.java @@ -0,0 +1,75 @@ +package org.apache.maven.shared.io.location; + +/* + * 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. + */ + +import java.net.URL; + +import org.apache.maven.shared.io.logging.MessageHolder; + +/** + * classpath resource locator strategy. + * + */ +public class ClasspathResourceLocatorStrategy + implements LocatorStrategy +{ + + private String tempFilePrefix = "location."; + + private String tempFileSuffix = ".cpurl"; + + private boolean tempFileDeleteOnExit = true; + + /** + * Create instance. + */ + public ClasspathResourceLocatorStrategy() + { + } + + /** + * @param tempFilePrefix Prefix. + * @param tempFileSuffix Suffix. + * @param tempFileDeleteOnExit delete on exit. + */ + public ClasspathResourceLocatorStrategy( String tempFilePrefix, String tempFileSuffix, + boolean tempFileDeleteOnExit ) + { + this.tempFilePrefix = tempFilePrefix; + this.tempFileSuffix = tempFileSuffix; + this.tempFileDeleteOnExit = tempFileDeleteOnExit; + } + + /** {@inheritDoc} */ +/** + * {@inheritDoc } + */ +public org.apache.maven.shared.io.location.Location resolve(java.lang.String locationSpecification, org.apache.maven.shared.io.logging.MessageHolder messageHolder) { + java.lang.ClassLoader cloader = java.lang.Thread.currentThread().getContextClassLoader(); + java.net.URL resource = cloader.getResource(locationSpecification); + org.apache.maven.shared.io.location.Location location = null; + { + location = new org.apache.maven.shared.io.location.URLLocation(/* NPEX_NULL_EXP */ + resource, locationSpecification, tempFilePrefix, tempFileSuffix, tempFileDeleteOnExit); + } + return location; +} + +} diff --git a/Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/metadata.json b/Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/metadata.json new file mode 100644 index 000000000..7a04a4efd --- /dev/null +++ b/Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-shared-io-ClasspathResourceLocatorStrategy_69", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "src/main/java/org/apache/maven/shared/io/location/ClasspathResourceLocatorStrategy.java", + "line": 70, + "npe_method": "resolve", + "deref_field": "resource", + "npe_class": "ClasspathResourceLocatorStrategy", + "repo": "maven-shared-io", + "bug_id": "ClasspathResourceLocatorStrategy_69" + } +} diff --git a/Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/npe.json b/Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/npe.json new file mode 100644 index 000000000..3729f11b7 --- /dev/null +++ b/Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/maven/shared/io/location/ClasspathResourceLocatorStrategy.java", + "line": 70, + "npe_method": "resolve", + "deref_field": "resource", + "npe_class": "ClasspathResourceLocatorStrategy" +} \ No newline at end of file diff --git a/Java/maven-shared-io-DefaultMessageHolder_293/Dockerfile b/Java/maven-shared-io-DefaultMessageHolder_293/Dockerfile new file mode 100644 index 000000000..4cf68844e --- /dev/null +++ b/Java/maven-shared-io-DefaultMessageHolder_293/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:maven-shared-io + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/maven-shared-io-DefaultMessageHolder_293/buggy.java b/Java/maven-shared-io-DefaultMessageHolder_293/buggy.java new file mode 100644 index 000000000..228134352 --- /dev/null +++ b/Java/maven-shared-io-DefaultMessageHolder_293/buggy.java @@ -0,0 +1,611 @@ +package org.apache.maven.shared.io.logging; + +/* + * 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. + */ + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Default Message Holder. + * + */ +public class DefaultMessageHolder + implements MessageHolder +{ + + private List messages = new ArrayList(); + + private Message currentMessage; + + private int defaultMessageLevel = MessageLevels.LEVEL_INFO; + + private boolean[] messageLevelStates; + + private MessageSink onDemandSink; + + /** + * Create instance. + */ + public DefaultMessageHolder() + { + this.messageLevelStates = MessageLevels.getLevelStates( MessageLevels.LEVEL_INFO ); + } + + /** + * @param maxMessageLevel max message level. + * @param defaultMessageLevel default message level. + */ + public DefaultMessageHolder( int maxMessageLevel, int defaultMessageLevel ) + { + this.defaultMessageLevel = defaultMessageLevel; + this.messageLevelStates = MessageLevels.getLevelStates( maxMessageLevel ); + } + + /** + * @param maxMessageLevel max message level. + * @param defaultMessageLevel default message level. + * @param onDemandSink {@link MessageSink} + */ + public DefaultMessageHolder( int maxMessageLevel, int defaultMessageLevel, MessageSink onDemandSink ) + { + this.defaultMessageLevel = defaultMessageLevel; + this.onDemandSink = onDemandSink; + this.messageLevelStates = MessageLevels.getLevelStates( maxMessageLevel ); + } + + /** {@inheritDoc} */ + public MessageHolder addMessage( CharSequence messagePart, Throwable error ) + { + return addMessage( defaultMessageLevel, messagePart, error ); + } + + /** + * @param level Level. + * @param messagePart Message part. + * @param error {@link Throwable} + * @return {@link MessageHolder} + */ + protected MessageHolder addMessage( int level, CharSequence messagePart, Throwable error ) + { + newMessage( level ); + append( messagePart.toString() ); + append( error ); + + return this; + } + + /** {@inheritDoc} */ + public MessageHolder addMessage( CharSequence messagePart ) + { + return addMessage( defaultMessageLevel, messagePart ); + } + + /** + * @param level level. + * @param messagePart message part. + * @return {@link MessageHolder} + */ + protected MessageHolder addMessage( int level, CharSequence messagePart ) + { + newMessage( level ); + append( messagePart.toString() ); + + return this; + } + + /** {@inheritDoc} */ + public MessageHolder addMessage( Throwable error ) + { + return addMessage( defaultMessageLevel, error ); + } + + /** + * @param level level. + * @param error {@link Throwable} + * @return {@link MessageHolder} + */ + protected MessageHolder addMessage( int level, Throwable error ) + { + newMessage( level ); + append( error ); + + return this; + } + + /** {@inheritDoc} */ + public MessageHolder append( CharSequence messagePart ) + { + if ( currentMessage == null ) + { + newMessage(); + } + + currentMessage.append( messagePart.toString() ); + + return this; + } + + /** {@inheritDoc} */ + public MessageHolder append( Throwable error ) + { + if ( currentMessage == null ) + { + newMessage(); + } + + currentMessage.setError( error ); + + return this; + } + + /** {@inheritDoc} */ + public boolean isEmpty() + { + return messages.isEmpty(); + } + + /** {@inheritDoc} */ + public MessageHolder newMessage() + { + newMessage( defaultMessageLevel ); + + return this; + } + + /** + * @param messageLevel message level. + */ + protected void newMessage( int messageLevel ) + { + if ( onDemandSink != null && currentMessage != null ) + { + renderTo( currentMessage, onDemandSink ); + } + + currentMessage = new Message( messageLevel, onDemandSink ); + messages.add( currentMessage ); + } + + /** {@inheritDoc} */ + public String render() + { + StringBuffer buffer = new StringBuffer(); + + int counter = 1; + for ( Iterator it = messages.iterator(); it.hasNext(); ) + { + Message message = (Message) it.next(); + + int ml = message.getMessageLevel(); + + if ( ml >= messageLevelStates.length || ml < 0 ) + { + ml = MessageLevels.LEVEL_DEBUG; + } + + if ( !messageLevelStates[ml] ) + { + continue; + } + + CharSequence content = message.render(); + String label = MessageLevels.getLevelLabel( message.getMessageLevel() ); + + if ( content.length() > label.length() + 3 ) + { + buffer.append( '[' ).append( counter++ ).append( "] " ); + buffer.append( content.toString() ); + + if ( it.hasNext() ) + { + buffer.append( "\n\n" ); + } + } + } + + return buffer.toString(); + } + + /** {@inheritDoc} */ + public int size() + { + return messages.size(); + } + + private static final class Message + { + private StringBuffer message = new StringBuffer(); + + private Throwable error; + + private final int messageLevel; + + private final MessageSink onDemandSink; + + Message( int messageLevel, MessageSink onDemandSink ) + { + this.messageLevel = messageLevel; + + this.onDemandSink = onDemandSink; + } + + public Message setError( Throwable pError ) + { + this.error = pError; + return this; + } + + public Message append( CharSequence pMessage ) + { + this.message.append( pMessage.toString() ); + return this; + } + + /** + * @return message level. + */ + public int getMessageLevel() + { + return messageLevel; + } + + /** + * @return Sequence. + */ +/** + * + * + * @return Sequence. + */ +public java.lang.CharSequence render() { + java.lang.StringBuffer buffer = new java.lang.StringBuffer(); + if (onDemandSink == null) { + buffer.append('[').append(org.apache.maven.shared.io.logging.MessageLevels.getLevelLabel(messageLevel)).append("] "); + } + if ((message != null) && (message.length() > 0)) { + buffer.append(message); + if (error != null) { + buffer.append('\n'); + } + } + { + buffer.append("Error:\n"); + java.io.StringWriter sw = new java.io.StringWriter(); + java.io.PrintWriter pw = new java.io.PrintWriter(sw); + /* NPEX_NULL_EXP */ + error.printStackTrace(pw); + buffer.append(sw.toString()); + } + return buffer; +} + } + + /** {@inheritDoc} */ + public MessageHolder addDebugMessage( CharSequence messagePart, Throwable error ) + { + return addMessage( MessageLevels.LEVEL_DEBUG, messagePart, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addDebugMessage( CharSequence messagePart ) + { + return addMessage( MessageLevels.LEVEL_DEBUG, messagePart ); + } + + /** {@inheritDoc} */ + public MessageHolder addDebugMessage( Throwable error ) + { + return addMessage( MessageLevels.LEVEL_DEBUG, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addErrorMessage( CharSequence messagePart, Throwable error ) + { + return addMessage( MessageLevels.LEVEL_ERROR, messagePart, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addErrorMessage( CharSequence messagePart ) + { + return addMessage( MessageLevels.LEVEL_ERROR, messagePart ); + } + + /** {@inheritDoc} */ + public MessageHolder addErrorMessage( Throwable error ) + { + return addMessage( MessageLevels.LEVEL_ERROR, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addInfoMessage( CharSequence messagePart, Throwable error ) + { + return addMessage( MessageLevels.LEVEL_INFO, messagePart, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addInfoMessage( CharSequence messagePart ) + { + return addMessage( MessageLevels.LEVEL_INFO, messagePart ); + } + + /** {@inheritDoc} */ + public MessageHolder addInfoMessage( Throwable error ) + { + return addMessage( MessageLevels.LEVEL_INFO, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addSevereMessage( CharSequence messagePart, Throwable error ) + { + return addMessage( MessageLevels.LEVEL_SEVERE, messagePart, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addSevereMessage( CharSequence messagePart ) + { + return addMessage( MessageLevels.LEVEL_SEVERE, messagePart ); + } + + /** {@inheritDoc} */ + public MessageHolder addSevereMessage( Throwable error ) + { + return addMessage( MessageLevels.LEVEL_SEVERE, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addWarningMessage( CharSequence messagePart, Throwable error ) + { + return addMessage( MessageLevels.LEVEL_WARNING, messagePart, error ); + } + + /** {@inheritDoc} */ + public MessageHolder addWarningMessage( CharSequence messagePart ) + { + return addMessage( MessageLevels.LEVEL_WARNING, messagePart ); + } + + /** {@inheritDoc} */ + public MessageHolder addWarningMessage( Throwable error ) + { + return addMessage( MessageLevels.LEVEL_WARNING, error ); + } + + /** {@inheritDoc} */ + public int countDebugMessages() + { + return countMessagesOfType( MessageLevels.LEVEL_DEBUG ); + } + + /** {@inheritDoc} */ + public int countErrorMessages() + { + return countMessagesOfType( MessageLevels.LEVEL_ERROR ); + } + + /** {@inheritDoc} */ + public int countInfoMessages() + { + return countMessagesOfType( MessageLevels.LEVEL_INFO ); + } + + /** {@inheritDoc} */ + public int countMessages() + { + return size(); + } + + /** {@inheritDoc} */ + public int countSevereMessages() + { + return countMessagesOfType( MessageLevels.LEVEL_SEVERE ); + } + + /** {@inheritDoc} */ + public int countWarningMessages() + { + return countMessagesOfType( MessageLevels.LEVEL_WARNING ); + } + + /** + * @param messageLevel leve. + * @return number of messages. + */ + private int countMessagesOfType( int messageLevel ) + { + int count = 0; + + for ( Message message : messages ) + { + if ( messageLevel == message.getMessageLevel() ) + { + count++; + } + } + + return count; + } + + /** {@inheritDoc} */ + public boolean isDebugEnabled() + { + return messageLevelStates[MessageLevels.LEVEL_DEBUG]; + } + + /** {@inheritDoc} */ + public boolean isErrorEnabled() + { + return messageLevelStates[MessageLevels.LEVEL_ERROR]; + } + + /** {@inheritDoc} */ + public boolean isInfoEnabled() + { + return messageLevelStates[MessageLevels.LEVEL_INFO]; + } + + /** {@inheritDoc} */ + public boolean isSevereEnabled() + { + return messageLevelStates[MessageLevels.LEVEL_SEVERE]; + } + + /** {@inheritDoc} */ + public boolean isWarningEnabled() + { + return messageLevelStates[MessageLevels.LEVEL_WARNING]; + } + + /** {@inheritDoc} */ + public MessageHolder newDebugMessage() + { + if ( isDebugEnabled() ) + { + newMessage( MessageLevels.LEVEL_DEBUG ); + } + + return this; + } + + /** {@inheritDoc} */ + public MessageHolder newErrorMessage() + { + if ( isErrorEnabled() ) + { + newMessage( MessageLevels.LEVEL_ERROR ); + } + + return this; + } + + /** {@inheritDoc} */ + public MessageHolder newInfoMessage() + { + if ( isInfoEnabled() ) + { + newMessage( MessageLevels.LEVEL_INFO ); + } + + return this; + } + + /** {@inheritDoc} */ + public MessageHolder newSevereMessage() + { + if ( isSevereEnabled() ) + { + newMessage( MessageLevels.LEVEL_SEVERE ); + } + + return this; + } + + /** {@inheritDoc} */ + public MessageHolder newWarningMessage() + { + if ( isWarningEnabled() ) + { + newMessage( MessageLevels.LEVEL_WARNING ); + } + + return this; + } + + /** {@inheritDoc} */ + public void setDebugEnabled( boolean enabled ) + { + messageLevelStates[MessageLevels.LEVEL_DEBUG] = enabled; + } + + /** {@inheritDoc} */ + public void setErrorEnabled( boolean enabled ) + { + messageLevelStates[MessageLevels.LEVEL_ERROR] = enabled; + } + + /** {@inheritDoc} */ + public void setInfoEnabled( boolean enabled ) + { + messageLevelStates[MessageLevels.LEVEL_INFO] = enabled; + } + + /** {@inheritDoc} */ + public void setSevereEnabled( boolean enabled ) + { + messageLevelStates[MessageLevels.LEVEL_SEVERE] = enabled; + } + + /** {@inheritDoc} */ + public void setWarningEnabled( boolean enabled ) + { + messageLevelStates[MessageLevels.LEVEL_WARNING] = enabled; + } + + /** {@inheritDoc} */ + public void flush() + { + if ( onDemandSink != null && currentMessage != null ) + { + renderTo( currentMessage, onDemandSink ); + currentMessage = null; + } + } + + /** {@inheritDoc} */ + public void render( MessageSink sink ) + { + for ( Message message : messages ) + { + renderTo( message, sink ); + } + } + + /** + * @param message {@link Message} + * @param sink {@link MessageSink} + */ + protected void renderTo( Message message, MessageSink sink ) + { + switch ( message.getMessageLevel() ) + { + case ( MessageLevels.LEVEL_SEVERE ): + sink.severe( message.render().toString() ); + break; + + case ( MessageLevels.LEVEL_ERROR ): + sink.error( message.render().toString() ); + break; + + case ( MessageLevels.LEVEL_WARNING ): + sink.warning( message.render().toString() ); + break; + + case ( MessageLevels.LEVEL_INFO ): + sink.info( message.render().toString() ); + break; + + default: + sink.debug( message.render().toString() ); + } + } + +} diff --git a/Java/maven-shared-io-DefaultMessageHolder_293/metadata.json b/Java/maven-shared-io-DefaultMessageHolder_293/metadata.json new file mode 100644 index 000000000..bfaa23cd6 --- /dev/null +++ b/Java/maven-shared-io-DefaultMessageHolder_293/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "maven-shared-io-DefaultMessageHolder_293", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "src/main/java/org/apache/maven/shared/io/logging/DefaultMessageHolder.java", + "line": 296, + "npe_method": "render", + "deref_field": "error", + "npe_class": "Message", + "repo": "maven-shared-io", + "bug_id": "DefaultMessageHolder_293" + } +} diff --git a/Java/maven-shared-io-DefaultMessageHolder_293/npe.json b/Java/maven-shared-io-DefaultMessageHolder_293/npe.json new file mode 100644 index 000000000..737f86e15 --- /dev/null +++ b/Java/maven-shared-io-DefaultMessageHolder_293/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/maven/shared/io/logging/DefaultMessageHolder.java", + "line": 296, + "npe_method": "render", + "deref_field": "error", + "npe_class": "Message" +} \ No newline at end of file From 01bde7e681cef25589d209b8d05e0576b3ddcfdd Mon Sep 17 00:00:00 2001 From: junheeL Date: Fri, 1 Dec 2023 10:36:42 +0900 Subject: [PATCH 3/3] fix(java): metadata --- Java/maven-shared-io-ArtifactLocatorStrategy_150/metadata.json | 2 +- .../metadata.json | 2 +- Java/maven-shared-io-DefaultMessageHolder_293/metadata.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Java/maven-shared-io-ArtifactLocatorStrategy_150/metadata.json b/Java/maven-shared-io-ArtifactLocatorStrategy_150/metadata.json index 860aa3b6a..9c7d44cd0 100644 --- a/Java/maven-shared-io-ArtifactLocatorStrategy_150/metadata.json +++ b/Java/maven-shared-io-ArtifactLocatorStrategy_150/metadata.json @@ -4,7 +4,7 @@ "buggyPath": ".", "referencePath": null, "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", - "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "testCommand": "mvn clean test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", "categories": [ "safety", "npe" diff --git a/Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/metadata.json b/Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/metadata.json index 7a04a4efd..30c12deb8 100644 --- a/Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/metadata.json +++ b/Java/maven-shared-io-ClasspathResourceLocatorStrategy_69/metadata.json @@ -4,7 +4,7 @@ "buggyPath": ".", "referencePath": null, "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", - "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "testCommand": "mvn clean test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", "categories": [ "safety", "npe" diff --git a/Java/maven-shared-io-DefaultMessageHolder_293/metadata.json b/Java/maven-shared-io-DefaultMessageHolder_293/metadata.json index bfaa23cd6..3f8947675 100644 --- a/Java/maven-shared-io-DefaultMessageHolder_293/metadata.json +++ b/Java/maven-shared-io-DefaultMessageHolder_293/metadata.json @@ -4,7 +4,7 @@ "buggyPath": ".", "referencePath": null, "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", - "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "testCommand": "mvn clean test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", "categories": [ "safety", "npe"