Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
… a new class of license representing the Apache Software License as usually applied outside the ASF. Thanks to Ate Douma for the patch.

git-svn-id: https://svn.apache.org/repos/asf/creadur/rat/trunk@1447920 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
itstechupnorth committed Feb 19, 2013
1 parent 3f280f2 commit 990e0b9
Show file tree
Hide file tree
Showing 4 changed files with 365 additions and 0 deletions.
@@ -0,0 +1,94 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one *
* or more contributor license agreements. See the NOTICE file *
* distributed with this work for additional information *
* regarding copyright ownership. The ASF licenses this file *
* to you under the Apache License, Version 2.0 (the *
* "License"); you may not use this file except in compliance *
* with the License. You may obtain a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, *
* software distributed under the License is distributed on an *
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
*/
package org.apache.rat.analysis.license;

import java.util.regex.Pattern;

import org.apache.rat.analysis.RatHeaderAnalysisException;
import org.apache.rat.api.Document;
import org.apache.rat.api.MetaData;

/**
* Matches an applied ASL 2.0 License header, including a <em>required</em>
* initial copyright header line, conforming the <a href="http://apache.org/licenses/LICENSE-2.0.html#apply">template</a>
* from the ASL 2.0 license itself.
*
* @since Rat 0.9
*/
public class AppliedApacheSoftwareLicense20 extends CopyrightHeader {

public static final String ASL20_LICENSE_DEFN
= "Licensed under the Apache License, Version 2.0 (the \"License\");\n"
+ "you may not use this file except in compliance with the License.\n"
+ "You may obtain a copy of the License at\n"
+ "http://www.apache.org/licenses/LICENSE-2.0\n"
+ "Unless required by applicable law or agreed to in writing, software\n"
+ "distributed under the License is distributed on an \"AS IS\" BASIS,\n"
+ "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
+ "See the License for the specific language governing permissions and\n"
+ "limitations under the License.\n";

protected static final Pattern LICENSE_PATTERN = Pattern.compile(".*" + prune(ASL20_LICENSE_DEFN) + ".*", Pattern.CASE_INSENSITIVE);

protected static String prune(String text) {
StringBuilder buffer = new StringBuilder(text);
int length = buffer.length();
for (int i = length; i > 0;) {
char at = buffer.charAt(--i);
if (!Character.isLetterOrDigit(at)) {
buffer.deleteCharAt(i);
}
}
return buffer.toString();
}

private StringBuilder buffer = new StringBuilder();

public AppliedApacheSoftwareLicense20() {
super(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_ASL, MetaData.RAT_LICENSE_FAMILY_NAME_DATUM_APACHE_LICENSE_VERSION_2_0,"");
}

public AppliedApacheSoftwareLicense20(String copyrightOwner) {
this();
setCopyrightOwner(copyrightOwner);
}

@Override
public boolean match(Document subject, String s) throws RatHeaderAnalysisException {
boolean result = false;
if (isCopyrightMatch()) {
buffer.append(prune(s));
if (LICENSE_PATTERN.matcher(buffer).matches()) {
reportOnLicense(subject);
return true;
}
return false;
}
else {
matchCopyright(s);
}
return result;
}

@Override
public void reset() {
super.reset();
buffer.setLength(0);
}
}
@@ -0,0 +1,103 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one *
* or more contributor license agreements. See the NOTICE file *
* distributed with this work for additional information *
* regarding copyright ownership. The ASF licenses this file *
* to you under the Apache License, Version 2.0 (the *
* "License"); you may not use this file except in compliance *
* with the License. You may obtain a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, *
* software distributed under the License is distributed on an *
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
*/
package org.apache.rat.analysis.license;

import java.util.regex.Pattern;

import org.apache.rat.analysis.IHeaderMatcher;
import org.apache.rat.analysis.RatHeaderAnalysisException;
import org.apache.rat.api.Document;
import org.apache.rat.api.MetaData.Datum;

/**
* Matches a typical Copyright header line only based on a regex pattern
* which allows for one (starting) year or year range, and a
* configurable copyright owner.
*
* <p>The matching is done case insensitive</p>
*
* <ul>Example supported Copyright header lines, using copyright owner "FooBar"
* <li>* Copyright 2010 FooBar. *</li>
* <li>* Copyright 2010-2012 FooBar. *</li>
* <li>*copyright 2012 foobar*</li>
* </ul>
*
* <p>Note also that the copyright owner is appended to the regex pattern, so
* can support additional regex but also requires escaping where needed,<br/>
* e.g. use "FooBar \(www\.foobar\.com\)" for matching "FooBar (www.foobar.com)" </p>
*
* @since Rat 0.9
*/
public class CopyrightHeader extends BaseLicense implements IHeaderMatcher {

public static final String COPYRIGHT_PREFIX_PATTERN_DEFN = ".*Copyright [0-9]{4}(\\-[0-9]{4})? ";

private Pattern copyrightPattern;
private String copyrightOwner;
private boolean copyrightMatch = false;

public CopyrightHeader(){
}

protected CopyrightHeader(Datum licenseFamilyCategory, Datum licenseFamilyName, String notes) {
super(licenseFamilyCategory, licenseFamilyName, notes);
}

protected CopyrightHeader(Datum licenseFamilyCategory, Datum licenseFamilyName, String notes, String copyrightOwner) {
this(licenseFamilyCategory, licenseFamilyName, notes);
setCopyrightOwner(copyrightOwner);
}

public void setCopyrightOwner(String copyrightOwner) {
this.copyrightOwner = copyrightOwner;
this.copyrightPattern = Pattern.compile(COPYRIGHT_PREFIX_PATTERN_DEFN+copyrightOwner+".*", Pattern.CASE_INSENSITIVE);
}

public String getCopyRightOwner() {
return copyrightOwner;
}

public boolean hasCopyrightPattern() {
return copyrightPattern != null;
}

protected boolean isCopyrightMatch() {
return copyrightMatch;
}

protected boolean matchCopyright(String s) throws RatHeaderAnalysisException {
if (!copyrightMatch) {
copyrightMatch = copyrightPattern.matcher(s).matches();
}
return copyrightMatch;
}

public boolean match(Document subject, String s) throws RatHeaderAnalysisException {
if (!copyrightMatch) {
if (matchCopyright(s)) {
reportOnLicense(subject);
}
}
return copyrightMatch;
}

public void reset() {
copyrightMatch = false;
}
}
@@ -0,0 +1,92 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one *
* or more contributor license agreements. See the NOTICE file *
* distributed with this work for additional information *
* regarding copyright ownership. The ASF licenses this file *
* to you under the Apache License, Version 2.0 (the *
* "License"); you may not use this file except in compliance *
* with the License. You may obtain a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, *
* software distributed under the License is distributed on an *
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
*/
package org.apache.rat.analysis.license;

import java.io.BufferedReader;
import java.io.StringReader;

import org.apache.rat.api.Document;
import org.apache.rat.document.MockLocation;
import org.apache.rat.report.claim.impl.xml.MockClaimReporter;
import org.apache.rat.test.utils.Resources;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class AppliedApacheSoftwareLicense20Test {

private static final String HEADER
= "/*\n"
+ " * Copyright 2012-2013 FooBar.\n"
+ " *\n"
+ " * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
+ " * you may not use this file except in compliance with the License.\n"
+ " *\n"
+ " * You may obtain a copy of the License at\n"
+ " * http://www.apache.org/licenses/LICENSE-2.0\n"
+ " *\n"
+ " * Unless required by applicable law or agreed to in writing, software\n"
+ " * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
+ " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
+ " * See the License for the specific language governing permissions and\n"
+ " * limitations under the License.\n"
+ " */\n";

AppliedApacheSoftwareLicense20 license;

MockClaimReporter reporter;

@Before
public void setUp() throws Exception {
license = new AppliedApacheSoftwareLicense20("FooBar");
reporter = new MockClaimReporter();
}

@Test
public void match() throws Exception {
BufferedReader in = new BufferedReader(new StringReader(HEADER));
String line = in.readLine();
boolean result = false;
final Document subject = new MockLocation("subject");
while (line != null) {
result = license.match(subject, line);
line = in.readLine();
}
assertTrue("Applied ASL2.0 license should be matched", result);
license.reset();
result = license.match(subject, "New line");
assertFalse("After reset, content should build up again", result);
}

@Test
public void noMatch() throws Exception {
BufferedReader in = Resources.getBufferedResourceReader("elements/Source.java");
String line = in.readLine();
boolean result = false;
final Document subject = new MockLocation("subject");
while (line != null) {
result = license.match(subject, line);
line = in.readLine();
}
assertFalse("Applied ASL2.0 license should not be matched", result);
license.reset();
}
}
@@ -0,0 +1,76 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one *
* or more contributor license agreements. See the NOTICE file *
* distributed with this work for additional information *
* regarding copyright ownership. The ASF licenses this file *
* to you under the Apache License, Version 2.0 (the *
* "License"); you may not use this file except in compliance *
* with the License. You may obtain a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, *
* software distributed under the License is distributed on an *
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
*/
package org.apache.rat.analysis.license;

import org.apache.rat.api.Document;
import org.apache.rat.api.MetaData;
import org.apache.rat.document.MockLocation;
import org.apache.rat.report.claim.impl.xml.MockClaimReporter;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class CopyrightHeaderTest {

private static final String[] MATCHING_HEADERS =
{ "/* Copyright 2012 FooBar.*/"
, "/* copyright 2012 foobar.*/"
, "/* Copyright 2012-2013 FooBar.*/" };
private static final String[] NON_MATCHING_HEADERS =
{ "/* Copyright*/"
, "/* Copyright FooBar.*/"
, "/* Copyright 2013*/"
, "/* Copyright 123a*/"
, "/* Copyright 123f oobar*/"
, "/* Copyright 2013FooBar*/"
, "/* Copyright 2012 2013 FooBar.*/" };

CopyrightHeader header;
MockClaimReporter reporter;
Document subject = new MockLocation("subject");

@Before
public void setUp() throws Exception {
header = new CopyrightHeader(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_ASL,MetaData.RAT_LICENSE_FAMILY_NAME_DATUM_APACHE_LICENSE_VERSION_2_0,"","FooBar");
reporter = new MockClaimReporter();
subject = new MockLocation("subject");
}

@Test
public void match() throws Exception {
for (String line : MATCHING_HEADERS) {
assertTrue("Copyright Header should be matched", header.match(subject, line));
header.reset();
assertFalse("After reset, content should build up again", header.match(subject, "New line"));
header.reset();
}
}

@Test
public void noMatch() throws Exception {
for (String line : NON_MATCHING_HEADERS) {
assertFalse("Copyright Header shouldn't be matched", header.match(subject, line));
header.reset();
assertTrue("After reset, content should build up again", header.match(subject, MATCHING_HEADERS[0]));
header.reset();
}
}
}

0 comments on commit 990e0b9

Please sign in to comment.