diff --git a/.gitignore b/.gitignore
index c4496c4..0fb77b0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,4 +12,3 @@ bin
*.log
*.jar
-metrics/
diff --git a/pom.xml b/pom.xml
index 4ef511c..aae78cf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -92,7 +92,7 @@
org.slf4j
slf4j-log4j12
- 1.6.6
+ 1.7.6
org.apache.commons
@@ -175,25 +175,25 @@
4.11
- org.gitective
- gitective-core
- 0.9.9
-
-
- org.mongodb
- mongo-java-driver
- 2.11.3
+ org.mongodb
+ mongo-java-driver
+ 2.11.3
- org.mongodb.morphia
- morphia
- 0.105
+ org.mongodb.morphia
+ morphia
+ 0.105
- de.flapdoodle.embed
- de.flapdoodle.embed.mongo
- 1.42
-
+ org.eclipse.jdt
+ org.eclipse.jdt.core
+ 3.7.1
+
+
+ de.flapdoodle.embed
+ de.flapdoodle.embed.mongo
+ 1.40
+
@@ -247,6 +247,7 @@
org.apache.maven.plugins
maven-source-plugin
+ 2.2.1
attach-sources
@@ -260,6 +261,7 @@
org.apache.maven.plugins
maven-javadoc-plugin
+ 2.9.1
attach-javadocs
@@ -287,7 +289,7 @@
-
+
diff --git a/src/java/main/br/ufpe/cin/groundhog/database/GroundhogDB.java b/src/java/main/br/ufpe/cin/groundhog/database/GroundhogDB.java
index dfb2270..18d54ac 100644
--- a/src/java/main/br/ufpe/cin/groundhog/database/GroundhogDB.java
+++ b/src/java/main/br/ufpe/cin/groundhog/database/GroundhogDB.java
@@ -4,6 +4,7 @@
import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.Morphia;
+import org.mongodb.morphia.Key;
import br.ufpe.cin.groundhog.GitHubEntity;
@@ -17,14 +18,17 @@
*
*/
public class GroundhogDB {
- private final String dbName;
- private final MongoClient mongo;
- private final Datastore datastore;
+
+ private String dbName;
+ private MongoClient mongo;
+ private Datastore datastore;
+ private Morphia mapper;
public GroundhogDB(String host, String dbName) throws UnknownHostException {
this.dbName = dbName;
this.mongo = new MongoClient(host);
- this.datastore = new Morphia().createDatastore(this.mongo, dbName);
+ this.mapper = new Morphia();
+ this.datastore = this.mapper.createDatastore(this.mongo, dbName);
}
public GroundhogDB(MongoClient mongo, String dbName) throws UnknownHostException {
@@ -41,8 +45,8 @@ public static void query(GitHubEntity entity, String params) {
* Receives a GitHub entity object and persists it to the database
* @param entity, a {@link Object} representing one of the many GitHub entities covered by Groundhog
*/
- public void save(Object entity) {
- this.datastore.save(entity);
+ public Key save(T entity) {
+ return this.datastore.save(entity);
}
public String getDbName() {
@@ -56,4 +60,17 @@ public MongoClient getMongo() {
public Datastore getDatastore() {
return this.datastore;
}
-}
+
+ public void setDatastore(Datastore datastore) {
+ this.datastore = datastore;
+ }
+
+ public Morphia getMapper() {
+ return mapper;
+ }
+
+ public void setMapper(Morphia mapper) {
+ this.mapper = mapper;
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/main/br/ufpe/cin/groundhog/extractor/GitCommitExtractor.java b/src/java/main/br/ufpe/cin/groundhog/extractor/GitCommitExtractor.java
index 3e051fb..7ea7b05 100644
--- a/src/java/main/br/ufpe/cin/groundhog/extractor/GitCommitExtractor.java
+++ b/src/java/main/br/ufpe/cin/groundhog/extractor/GitCommitExtractor.java
@@ -41,6 +41,21 @@ public List extractCommits(File project) {
return null;
}
+ public List getCommitList(File project) {
+ CommitListFilter list = new CommitListFilter();
+
+ String path = project.getAbsolutePath() + "/.git";
+ CommitFinder finder = new CommitFinder(path);
+
+ finder.setFilter(list).find();
+//
+// for (RevCommit rev : list.getCommits()){
+// System.out.println(rev.getName() + " " + rev.getAuthorIdent().getName() + " " + rev.getShortMessage());
+// }
+//
+ return list.getCommits();
+ }
+
/**
* A method that returns the number of commits that contain files with a given file extension
* Example usage:
diff --git a/src/java/main/br/ufpe/cin/groundhog/main/CmdMain.java b/src/java/main/br/ufpe/cin/groundhog/main/CmdMain.java
index fe94563..d967b8e 100644
--- a/src/java/main/br/ufpe/cin/groundhog/main/CmdMain.java
+++ b/src/java/main/br/ufpe/cin/groundhog/main/CmdMain.java
@@ -3,6 +3,7 @@
import static java.lang.String.format;
import java.io.File;
+import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
@@ -28,8 +29,14 @@
import br.ufpe.cin.groundhog.crawler.CrawlGoogleCode;
import br.ufpe.cin.groundhog.crawler.CrawlSourceForge;
import br.ufpe.cin.groundhog.crawler.ForgeCrawler;
+import br.ufpe.cin.groundhog.database.GroundhogDB;
import br.ufpe.cin.groundhog.http.HttpModule;
import br.ufpe.cin.groundhog.http.Requests;
+import br.ufpe.cin.groundhog.metrics.JavaProject;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidJavaFileException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidJavaProjectPathException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidSourceRootCodePathException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidTestSourcePathException;
import br.ufpe.cin.groundhog.parser.java.JavaParser;
import br.ufpe.cin.groundhog.parser.java.MutableInt;
import br.ufpe.cin.groundhog.parser.java.NotAJavaProjectException;
@@ -171,7 +178,7 @@ public File downloadAndCheckoutProject(Project project,
File repositoryFolder = repositoryFolderFuture.get();
logger.info(format("Project %s was downloaded", name));
-
+
logger.info(format("Project has %d forks", project.getForksCount()));
logger.info(format("Checking out project %s to %s...", name, datetimeStr));
@@ -237,74 +244,99 @@ public void analyzeProject(Project project, File projectFolder,
@Override
public void run(JsonInputFile input) {
try {
- final File destinationFolder = input.getDest();
- final File metricsFolder = input.getOut();
-
- logger.info("Creating temp folders...");
- createTempFolders(destinationFolder, metricsFolder);
-
- final Date datetime = input.getDatetime();
- final int nProjects = input.getNprojects();
- final String username = input.getSearch().getUsername();
-
- // Search for projects
- logger.info("Searching for projects... " + input.getSearch().getProjects());
- ForgeSearch search = defineForgeSearch(input.getForge());
- ForgeCrawler crawler = defineForgeCrawler(input.getForge(), destinationFolder);
-
- String term = input.getSearch().getProjects().get(0);
- List allProjects = null;
- if(username != null && !username.isEmpty()) {
- allProjects = search.getProjects(term, username, 1);
- } else {
- allProjects = search.getProjects(term, 1,-1);
- }
-
- //TODO the getProjects method already limits the number of searched projects
- List projects = new ArrayList();
- for (int i = 0; i < nProjects; i++) {
- if (i < allProjects.size()) {
- projects.add(allProjects.get(i));
+ //Java Metrics
+ if(input.getDBName()!= null || input.getJavaProjectSourceRootPath() != null || input.getJavaProjectSourceRootTestPath() != null){
+
+ final GroundhogDB ghdb = new GroundhogDB("127.0.0.1", input.getDBName());
+ ghdb.getMapper().mapPackage("br.ufpe.cin.groundhog.metrics");
+
+ JavaProject project = new JavaProject(input.getJavaProjectPath());
+ try {
+ project.generateStructure(input.getJavaProjectSourceRootPath(), input.getJavaProjectSourceRootTestPath());
+ } catch (Exception e) {
+ logger.error("The struture of passed Java project can't be reconstructed!\nPlease check your parameters");
+ e.printStackTrace();
+ }
+
+ project.generateMetrics(
+ input.getJavaProjectSourceRootTestPath() != null ? true: false,
+ ghdb);
+
+ }else{
+
+ final File destinationFolder = input.getDest();
+ final File metricsFolder = input.getOut();
+
+ logger.info("Creating temp folders...");
+ createTempFolders(destinationFolder, metricsFolder);
+
+ final Date datetime = input.getDatetime();
+ final int nProjects = input.getNprojects();
+ final String username = input.getSearch().getUsername();
+
+ // Search for projects
+ logger.info("Searching for projects... " + input.getSearch().getProjects());
+ ForgeSearch search = defineForgeSearch(input.getForge());
+ ForgeCrawler crawler = defineForgeCrawler(input.getForge(), destinationFolder);
+
+ String term = input.getSearch().getProjects().get(0);
+
+ List allProjects = null;
+ if(username != null && !username.isEmpty()) {
+ allProjects = search.getProjects(term, username, 1);
+ } else {
+ allProjects = search.getProjects(term, 1,-1);
}
- }
-
- // Download and analyze projects
- logger.info("Downloading and processing projects...");
- ExecutorService ex = Executors.newFixedThreadPool(JsonInputFile.getMaxThreads());
- List> downloadFutures = crawler.asyncDownloadProjects(projects);
- List> analysisFutures = new ArrayList>();
-
- for (int i = 0; i < downloadFutures.size(); i++) {
- final Project project = projects.get(i);
- final Future repositoryFolderFuture = downloadFutures.get(i);
- final Formater metricsFormat = input.getOutputformat();
- analysisFutures.add(ex.submit(new Runnable() {
- @Override
- public void run() {
- File checkedOutRepository = downloadAndCheckoutProject(project, datetime, repositoryFolderFuture);
+ //TODO the getProjects method already limits the number of searched projects
+ List projects = new ArrayList();
+ for (int i = 0; i < nProjects; i++) {
+ if (i < allProjects.size()) {
+ projects.add(allProjects.get(i));
+ }
+ }
- if (checkedOutRepository != null) {
- analyzeProject(project, checkedOutRepository, datetime, metricsFolder, metricsFormat);
+ // Download and analyze projects
+ logger.info("Downloading and processing projects...");
+ ExecutorService ex = Executors.newFixedThreadPool(JsonInputFile.getMaxThreads());
+ List> downloadFutures = crawler.asyncDownloadProjects(projects);
+ List> analysisFutures = new ArrayList>();
+
+ for (int i = 0; i < downloadFutures.size(); i++) {
+ final Project project = projects.get(i);
+ final Future repositoryFolderFuture = downloadFutures.get(i);
+ final Formater metricsFormat = input.getOutputformat();
+
+ analysisFutures.add(ex.submit(new Runnable() {
+ @Override
+ public void run() {
+ File checkedOutRepository = downloadAndCheckoutProject(project, datetime, repositoryFolderFuture);
+
+ if (checkedOutRepository != null) {
+ analyzeProject(project, checkedOutRepository, datetime, metricsFolder, metricsFormat);
+ }
}
- }
- }));
- }
+ }));
+ }
- ex.shutdown();
- for (int i = 0; i < analysisFutures.size(); i++) {
- try {
- analysisFutures.get(i).get();
- } catch (InterruptedException | ExecutionException e) {
- logger.error(format("Error while analyzing project %s", projects.get(i).getName()), e);
+ ex.shutdown();
+ for (int i = 0; i < analysisFutures.size(); i++) {
+ try {
+ analysisFutures.get(i).get();
+ } catch (InterruptedException | ExecutionException e) {
+ logger.error(format("Error while analyzing project %s", projects.get(i).getName()), e);
+ }
}
+ logger.info("All projects were downloaded and analyzed!");
}
- logger.info("All projects were downloaded and analyzed!");
-
+
} catch (GroundhogException e) {
e.printStackTrace();
logger.error(e.getMessage());
+ } catch (UnknownHostException e1) {
+ e1.printStackTrace();
+ logger.error("Fail to acess MongoDB database, please check if its installed and running");
}
}
diff --git a/src/java/main/br/ufpe/cin/groundhog/main/CmdOptions.java b/src/java/main/br/ufpe/cin/groundhog/main/CmdOptions.java
index 11c86e2..c55afad 100644
--- a/src/java/main/br/ufpe/cin/groundhog/main/CmdOptions.java
+++ b/src/java/main/br/ufpe/cin/groundhog/main/CmdOptions.java
@@ -51,6 +51,26 @@ public class CmdOptions {
@Option(name = "-githubtoken", usage = "use authenticated requests to github api")
private String gitHubOauthAcessToken;
+ @Option(name = "-jm", usage = "use to extract some metrics from java projects, like McGabe complexity and total lines of code (TLOC), to the project passed\n"
+ + "By default the path is your actual directory",
+ aliases = {"--generate-java-metrics"}, metaVar = "")
+ private File projectPath = new File(System.getProperty("user.dir"));
+
+ @Option(name = "-src", usage = "use this option to provide the path of source root code directory from project root",
+ aliases = {"--source-root-code"}, metaVar = "")
+ private File child_path_src;
+
+ @Option(name = "-srtc", usage = "use this option to provide the path of source root code directory from project root",
+ aliases = {"--source-root-test-code"}, metaVar = "")
+ private File child_path_srtc;
+
+ @Option(name = "-dm", usage = "use this option to provide the name of Groundhog database when the generated metrics will be stored.\n"
+ + "By default the database name are java_metrics",
+ aliases = {"--database-name"})
+ private String dbName = "java_metrics";
+
+
+
private JsonInputFile input = null;
@Argument
@@ -172,7 +192,47 @@ public String getGitHubOauthAcessToken() {
public void setGitHubOauthAcessToken(String gitHubOauthAcessToken) {
this.gitHubOauthAcessToken = gitHubOauthAcessToken;
}
+
+ public File getProjectPath() {
+ return projectPath;
+ }
+
+ public void setProjectPath(File projectPath) {
+ this.projectPath = projectPath;
+ }
+
+ public File getChild_path_src() {
+ return child_path_src;
+ }
+
+ public void setChild_path_src(File child_path_src) {
+ this.child_path_src = child_path_src;
+ }
+ public File getChild_path_srtc() {
+ return child_path_srtc;
+ }
+
+ public void setChild_path_srtc(File child_path_srtc) {
+ this.child_path_srtc = child_path_srtc;
+ }
+
+ public String getDbName() {
+ return dbName;
+ }
+
+ public void setDbName(String dbName) {
+ this.dbName = dbName;
+ }
+
+ public JsonInputFile getInput() {
+ return input;
+ }
+
+ public void setInput(JsonInputFile input) {
+ this.input = input;
+ }
+
@Option(name = "-in", usage = "all inputs together in one json file")
public void setInputFile(File inputFile) {
try {
diff --git a/src/java/main/br/ufpe/cin/groundhog/main/JsonInputFile.java b/src/java/main/br/ufpe/cin/groundhog/main/JsonInputFile.java
index 3c60238..9a6a1e5 100644
--- a/src/java/main/br/ufpe/cin/groundhog/main/JsonInputFile.java
+++ b/src/java/main/br/ufpe/cin/groundhog/main/JsonInputFile.java
@@ -27,6 +27,10 @@ public final class JsonInputFile {
private String outputformat;
private Search search;
private String gitHubOauthAcessToken;
+ private File javaprojectpath;
+ private File child_path_src;
+ private File child_path_srtc;
+ private String dbname;
public JsonInputFile(CmdOptions opt) {
super();
@@ -38,6 +42,10 @@ public JsonInputFile(CmdOptions opt) {
this.outputformat = opt.getMetricsFormat();
this.search = new Search(opt.getArguments(), opt.getUsername());
this.gitHubOauthAcessToken = opt.getGitHubOauthAcessToken();
+ this.javaprojectpath = opt.getProjectPath();
+ this.child_path_src = opt.getChild_path_src();
+ this.child_path_srtc = opt.getChild_path_srtc();
+ this.dbname = opt.getDbName();
}
//TODO: this should be discovered dynamically
@@ -87,6 +95,36 @@ public Search getSearch() {
return this.search;
}
+ public File getJavaProjectPath(){
+ return this.javaprojectpath;
+ }
+
+ public File getJavaProjectSourceRootPath(){
+ if(this.child_path_src == null){
+ return null;
+ }else if(this.child_path_src.isDirectory()){
+ return this.child_path_src;
+ }else{
+ File to_return = new File(javaprojectpath, this.child_path_src.toString());
+ return to_return;
+ }
+ }
+
+ public File getJavaProjectSourceRootTestPath(){
+ if(this.child_path_srtc == null){
+ return null;
+ }else if(this.child_path_srtc.isDirectory()){
+ return this.child_path_srtc;
+ }else{
+ File to_return = new File(javaprojectpath, this.child_path_srtc.toString());
+ return to_return;
+ }
+ }
+
+ public String getDBName(){
+ return this.dbname;
+ }
+
public String toString() {
return Objects.toStringHelper("")
.add("forge", forge)
@@ -96,6 +134,10 @@ public String toString() {
.add("nproject", nprojects)
.add("outputformat", outputformat)
.add("search", search)
+ .add("javaprojectpath", javaprojectpath)
+ .add("javaprojectsourcerootpath", child_path_src)
+ .add("javaprojectsourcetestrootpath", child_path_srtc)
+ .add("dbname", dbname)
.toString();
}
}
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/GroundhogASTVisitor.java b/src/java/main/br/ufpe/cin/groundhog/metrics/GroundhogASTVisitor.java
new file mode 100644
index 0000000..3e3d89d
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/GroundhogASTVisitor.java
@@ -0,0 +1,251 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import java.util.Stack;
+
+import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.dom.*;
+
+class GroundhogASTVisitor extends ASTVisitor{
+
+ Statistics stat;
+
+ /**
+ * Auxiliar fields to extract metrics
+ */
+ int methods = 0;
+ int fields = 0;
+ int methodCalls = 0;
+ int staticMethod = 0;
+ int staticField = 0;
+ int cycloComplexity = 1;
+ int returns = 0;
+
+ //fields used to nested block depth metric calculation
+ Stack depth = new Stack();
+ Stack maxDepth = new Stack();
+
+ /**
+ * Flag for preventing the calculation of methods from interfaces
+ */
+ boolean countMethods = true;
+
+ public boolean visit(AnonymousClassDeclaration node){
+ this.stat.anonymousClasses++;
+ return true;
+ }
+
+ public boolean visit(TypeDeclaration td){
+ if (td.isInterface()) {
+ this.countMethods = false;
+ this.stat.interfaces++;
+ } else {
+ this.countMethods = true;
+ this.stat.classes++;
+ }
+
+ this.fields = 0;
+ this.methods = 0;
+ this.staticMethod = 0;
+ this.staticField = 0;
+
+ return true;
+ }
+
+ public void endVisit(TypeDeclaration td){
+
+ Util.safeAddToHashTable(this.stat.fieldCounter, this.fields);
+ Util.safeAddToHashTable(this.stat.methodCounter,this.methods);
+ Util.safeAddToHashTable(this.stat.sMethodCounter,this.staticMethod);
+ Util.safeAddToHashTable(this.stat.sFieldCounter,this.staticField);
+ }
+
+ public boolean visit(MethodDeclaration md){
+
+ //We only take the metrics if the method isn't from an interface
+ if (this.countMethods) {
+
+ this.methods++;
+ this.methodCalls = 0;
+ this.cycloComplexity = 1;
+ this.returns = 0;
+
+ //nested block depth calculation
+ this.depth.push(0);
+ this.maxDepth.push(0);
+
+ String[] lines = md.toString().split("\n");
+ Util.safeAddToHashTable(this.stat.lineCounter,lines.length);
+ int f = md.getModifiers();
+ if(Flags.isStatic(f)) this.staticMethod++;
+ int param = md.parameters().size();
+ Util.safeAddToHashTable(this.stat.parameters,param);
+ }
+ return true;
+ }
+
+ public void endVisit(MethodDeclaration md){
+
+ //The same as the visit, we only take metrics if the method isn't from an interface
+ if (this.countMethods){
+
+ this.depth.pop();
+ int max = this.maxDepth.pop();
+ Util.safeAddStackTop(this.depth, max);
+ this.cycloComplexity += 2*Math.max(0, this.returns-1);
+ Util.safeAddToHashTable(this.stat.cycloCounter,this.cycloComplexity);
+ Util.safeAddToHashTable(this.stat.depCounter,max);
+ Util.safeAddToHashTable(this.stat.methodCall,this.methodCalls);
+ }
+ }
+
+ public boolean visit(MethodInvocation mi){
+ this.methodCalls++;
+ return true;
+ }
+
+ public boolean visit(ForStatement fs){
+ this.cycloComplexity++;
+ this.inspecionarExpressao(fs.getExpression());
+ return true;
+ }
+
+ public boolean visit(WhileStatement ws){
+ this.cycloComplexity++;
+ this.inspecionarExpressao(ws.getExpression());
+ return true;
+ }
+
+ public boolean visit(IfStatement is){
+ this.cycloComplexity++;
+ this.inspecionarExpressao(is.getExpression());
+ return true;
+ }
+
+ public boolean visit(BreakStatement bs){
+ this.cycloComplexity++;
+ return true;
+ }
+
+ public boolean visit(ContinueStatement cs){
+ this.cycloComplexity++;
+ return true;
+ }
+
+ public boolean visit(ExpressionStatement es){
+ this.inspecionarExpressao(es.getExpression());
+ return true;
+ }
+
+ public boolean visit(ConditionalExpression ce) {
+ cycloComplexity++;
+ inspecionarExpressao(ce.getExpression());
+ return true;
+ }
+
+ public boolean visit(DoStatement ds){
+ this.cycloComplexity++;
+ this.inspecionarExpressao(ds.getExpression());
+ return true;
+ }
+
+ public boolean visit(TryStatement ts){
+ if(ts.getFinally()!=null){
+ this.cycloComplexity++;
+ }
+ return true;
+ }
+
+ public boolean visit(CatchClause cc){
+ this.cycloComplexity++;
+ return true;
+ }
+
+ public boolean visit(ThrowStatement ts){
+ this.cycloComplexity++;
+ return true;
+ }
+
+ public boolean visit(SwitchCase sc){
+ this.cycloComplexity++;
+ return true;
+ }
+
+ public boolean visit(ReturnStatement rs){
+ this.returns++;
+ return true;
+ }
+
+ public boolean visit(FieldDeclaration fd){
+
+ this.fields++;
+ if(Flags.isStatic(fd.getModifiers())){
+ this.staticField++;
+ }
+
+ return true;
+ }
+
+ public boolean visit(Block node){
+
+ //Using an stack strategy to count the max nested block depth
+ //If I visit an block, so I have one more level of code
+ if(!this.depth.empty()){
+ /**
+ * We also want to calculate block nested depth for methods
+ * so, the stack will have at least one element if we was visited
+ * an method before
+ */
+ Util.safeAddStackTop(this.depth, 1);
+ }
+
+ return true;
+
+ }
+
+ public void endVisit(Block node) {
+ /**
+ * Using an stack strategy to count the max nested block depth
+ * If I end the visit of a block, so is time to check how deep the code are.
+ * If the actual nested level is more than actual maximum, so set maximum to
+ * this new maximum.
+ */
+ if(!this.depth.empty()){
+ /**
+ * We also want to calculate block nested depth for methods
+ * so, the stack will have at least one element if we was visited
+ * an method before
+ *
+ * Once I finish to visit a block, I need to reduce the nested level because
+ * we complete one sub-level of nested block
+ */
+ int temp = Util.safeAddStackTop(depth, -1);
+ if(temp > this.maxDepth.peek()){
+ this.maxDepth.pop();
+ this.maxDepth.push(temp);
+ }
+ }
+ }
+
+ public void inspecionarExpressao(Expression e) {
+ if (e != null) {
+ String expression = e.toString();
+ char[] chars = expression.toCharArray();
+ for (int i = 0; i < chars.length-1; i++) {
+ char next = chars[i];
+ if ((next == '&' || next == '|')&&(next == chars[i+1])) {
+ this.cycloComplexity++;
+ }
+ }
+ }
+ }
+
+ public void setStatistics(Statistics stat){
+ this.stat = stat;
+ }
+
+ public Statistics getStatistics(){
+ Statistics to_return = this.stat;
+ this.stat = null;
+ return to_return;
+ }
+}
\ No newline at end of file
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/JavaFile.java b/src/java/main/br/ufpe/cin/groundhog/metrics/JavaFile.java
new file mode 100644
index 0000000..b27fe9d
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/JavaFile.java
@@ -0,0 +1,173 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Scanner;
+
+import org.bson.types.ObjectId;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+
+import br.ufpe.cin.groundhog.database.GroundhogDB;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidJavaFileException;
+
+import com.google.gson.annotations.SerializedName;
+import org.mongodb.morphia.annotations.Entity;
+import org.mongodb.morphia.annotations.Id;
+import org.mongodb.morphia.annotations.Indexed;
+import org.mongodb.morphia.annotations.Reference;
+import org.mongodb.morphia.annotations.Transient;
+
+/**
+ * Represents a java class in Groundhog metrics extractor
+ * @author Bruno Soares, Tulio Lajes, Valdemir Andrade
+ * @since 0.1.0
+ */
+
+@Entity("javafiles")
+public class JavaFile {
+
+ /**
+ * Transient annotations will not be stored in the database
+ */
+
+ @Id
+ @Indexed(unique=true, dropDups=true)
+ ObjectId id;
+
+ @Transient
+ private File path;
+
+ @SerializedName("absolutepath")
+ private String absolutePath;
+
+ @SerializedName("name")
+ private String name;
+
+ @Transient
+ private ASTParser parser;
+
+ @Transient
+ private Scanner scanner;
+
+ @Transient
+ private CompilationUnit cu;
+
+ @Transient
+ private Statistics stat;
+
+ @Reference
+ @SerializedName("sttablefile")
+ private StatisticsTableFile table;
+
+ public Statistics getStat() {
+ return stat;
+ }
+
+ /**
+ * Default constructor used by morphia to create a empty object setting the annotated attributes using reflection
+ */
+ public JavaFile(){}
+
+ public JavaFile(File path, String name) throws InvalidJavaFileException{
+
+ this.path = path;
+ this.name = name;
+ commonInit();
+ }
+
+ public JavaFile(File path) throws InvalidJavaFileException{
+
+ this.path = path;
+ this.name = path.getName();
+ commonInit();
+ }
+
+ public JavaFile(String absolutePath, String name) throws InvalidJavaFileException{
+
+ this.path = new File(absolutePath);
+ this.name = name;
+ commonInit();
+
+ }
+
+ public JavaFile(String path) throws InvalidJavaFileException{
+
+ this.path = new File(path);
+ this.name = this.path.isFile() ? this.path.getName() : "";
+ commonInit();
+ }
+
+ private void commonInit() throws InvalidJavaFileException{
+
+ this.absolutePath = this.path.getAbsolutePath();
+ this.table = new StatisticsTableFile();
+
+ //Generate statistics structure
+ this.stat = new Statistics();
+ this.stat.compilationUnits++;
+
+ try{
+
+ //Read java file
+ this.scanner = new Scanner(this.path);
+ this.scanner.useDelimiter("\\Z");
+
+ //Generate AST
+ this.parser = ASTParser.newParser(AST.JLS3);
+ String source = this.scanner.next();
+ this.parser.setSource(source.toCharArray());
+
+ //Close scanner
+ this.scanner.close();
+
+ //Generate compilation unit to be visited
+ this.cu = (CompilationUnit) parser.createAST(null);
+ this.stat.totalCode = Util.countCodeLines(source);
+ }catch(FileNotFoundException e){
+
+ throw new InvalidJavaFileException();
+ }
+ }
+
+ @Override
+ public String toString(){
+
+ return "File: " + this.name;
+ }
+
+ public File getFile(){
+
+ return path;
+ }
+
+ public void setFile(File file){
+
+ this.path = file;
+ }
+
+ public StatisticsTableFile getTable() {
+ return table;
+ }
+
+ public void setTable(StatisticsTableFile table) {
+ this.table = table;
+ }
+
+ public Statistics generateMetrics(GroundhogASTVisitor visitor, MetricsCollector collector){
+
+ visitor.setStatistics(this.stat);
+ this.cu.accept(visitor);
+ this.stat = visitor.getStatistics();
+ collector.processFileLevel(this.table, this.stat);
+ return this.stat;
+ }
+
+ public Statistics generateMetrics(GroundhogASTVisitor visitor, MetricsCollector collector, GroundhogDB db){
+ Statistics to_return = generateMetrics(visitor, collector);
+ db.save(this.table);
+ db.save(this);
+ return to_return;
+ }
+}
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/JavaPackage.java b/src/java/main/br/ufpe/cin/groundhog/metrics/JavaPackage.java
new file mode 100644
index 0000000..c0832ee
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/JavaPackage.java
@@ -0,0 +1,196 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.bson.types.ObjectId;
+import org.mongodb.morphia.annotations.Entity;
+import org.mongodb.morphia.annotations.Id;
+import org.mongodb.morphia.annotations.Indexed;
+import org.mongodb.morphia.annotations.Reference;
+import org.mongodb.morphia.annotations.Transient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.annotations.SerializedName;
+
+import br.ufpe.cin.groundhog.database.GroundhogDB;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidJavaFileException;
+
+/**
+ * Represents a java package in Groundhog metrics extractor
+ * @author Bruno Soares, Tulio Lajes, Valdemir Andrade
+ * @since 0.1.0
+ */
+
+@Entity("javapackages")
+public class JavaPackage {
+
+ @Transient
+ private static Logger logger = LoggerFactory.getLogger(JavaProject.class);
+
+ @Id
+ @Indexed(unique=true, dropDups=true)
+ ObjectId id;
+
+ @Reference
+ @SerializedName("javafiles")
+ private ArrayList files;
+
+ @Transient
+ private File path;
+
+ @SerializedName("absolutepath")
+ private String absolutePath;
+
+ @SerializedName("name")
+ private String name;
+
+ @Transient
+ private Statistics statistics = new Statistics();
+
+ public ObjectId getId() {
+ return id;
+ }
+
+ public void setId(ObjectId id) {
+ this.id = id;
+ }
+
+ public ArrayList getFiles() {
+ return files;
+ }
+
+ public void setFiles(ArrayList files) {
+ this.files = files;
+ }
+
+ public File getPath() {
+ return path;
+ }
+
+ public void setPath(File path) {
+ this.path = path;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Statistics getStatistics() {
+ return statistics;
+ }
+
+ public void setStatistics(Statistics statistics) {
+ this.statistics = statistics;
+ }
+
+ public StatisticsTablePackage getTable() {
+ return table;
+ }
+
+ public void setTable(StatisticsTablePackage table) {
+ this.table = table;
+ }
+
+ @Reference
+ @SerializedName("sttablepackage")
+ private StatisticsTablePackage table;
+
+ /**
+ * Default constructor used by morphia to create a empty object setting the annotated attributes using reflection
+ */
+ public JavaPackage(){}
+
+ public JavaPackage(File path, String name) throws InvalidJavaFileException{
+ this.path = path;
+ this.name = name;
+ commonInit();
+ }
+
+ public JavaPackage(File path) throws InvalidJavaFileException{
+ this.path = path;
+ this.name = path.getName();
+ commonInit();
+ }
+
+ public JavaPackage(String absolutePath, String name) throws InvalidJavaFileException{
+ this.path = new File(absolutePath);
+ this.name = name;
+ commonInit();
+ }
+
+ public JavaPackage(String path) throws InvalidJavaFileException{
+ this.path = new File(path);
+ this.name = this.path.isDirectory() ? this.path.getName() : "";
+ commonInit();
+ }
+
+ public void commonInit() throws InvalidJavaFileException{
+ this.files = new ArrayList();
+ this.table = new StatisticsTablePackage();
+ detectJavaFiles();
+ }
+
+ @Override
+ public String toString() {
+ return "Package: " + this.name;
+ }
+
+ public List generateMetrics(GroundhogASTVisitor visitor, MetricsCollector collector){
+
+ List stats = new ArrayList();
+
+ //Collect metrics
+ for(JavaFile file : this.files){
+ stats.add(file.generateMetrics(visitor, collector));
+ }
+
+ collector.processPackageLevel(table, stats);
+ logger.debug(table.toString());
+ return stats;
+ }
+
+ public List generateMetrics(GroundhogASTVisitor visitor, MetricsCollector collector, GroundhogDB db){
+ List stats = new ArrayList();
+
+ //Collect metrics
+ for(JavaFile file : this.files){
+ stats.add(file.generateMetrics(visitor, collector,db));
+ }
+
+ collector.processPackageLevel(table, stats);
+
+ logger.debug(table.toString());
+
+ db.save(this.table);
+ db.save(this);
+
+ return stats;
+ }
+
+ private void detectJavaFiles() throws InvalidJavaFileException{
+
+ this.absolutePath = this.path.getAbsolutePath();
+ for (File file : this.path.listFiles()){
+ if(file.getName().endsWith(".java")){
+ this.files.add(new JavaFile(file,file.getName()));
+ logger.debug("Java File " + file.getName() + " detected!");
+ }
+ }
+ }
+
+ public String getAbsolutePath() {
+ return absolutePath;
+ }
+
+ public void setAbsolutePath(String absolutePath) {
+ this.absolutePath = absolutePath;
+ }
+
+}
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/JavaProject.java b/src/java/main/br/ufpe/cin/groundhog/metrics/JavaProject.java
new file mode 100644
index 0000000..9218040
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/JavaProject.java
@@ -0,0 +1,417 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+
+import org.bson.types.ObjectId;
+import org.mongodb.morphia.annotations.Entity;
+import org.mongodb.morphia.annotations.Id;
+import org.mongodb.morphia.annotations.Indexed;
+import org.mongodb.morphia.annotations.Reference;
+import org.mongodb.morphia.annotations.Transient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.annotations.SerializedName;
+
+import br.ufpe.cin.groundhog.database.GroundhogDB;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidJavaFileException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidJavaProjectPathException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidSourceRootCodePathException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidTestSourcePathException;
+
+/**
+ * Represents a java project in Groundhog metrics extractor
+ * @author Bruno Soares, Tulio Lajes, Valdemir Andrade
+ * @since 0.1.0
+ */
+
+@Entity("javaprojects")
+public class JavaProject {
+
+ @Transient
+ private static Logger logger = LoggerFactory.getLogger(JavaProject.class);
+
+ @Id
+ @Indexed(unique=true, dropDups=true)
+ private ObjectId id;
+
+ public static final String default_source_root_code = "src";
+
+ @Reference
+ private ArrayList code_packages;
+
+ @Reference
+ private ArrayList test_packages;
+
+ @Transient
+ private File path;
+
+ @Transient
+ private File src;
+
+ @Transient
+ private File srtc;
+
+ @SerializedName("absolutepath")
+ private String absolutePath;
+
+ public ObjectId getId() {
+ return id;
+ }
+
+ public void setId(ObjectId id) {
+ this.id = id;
+ }
+
+ public ArrayList getCode_packages() {
+ return code_packages;
+ }
+
+ public void setCode_packages(ArrayList code_packages) {
+ this.code_packages = code_packages;
+ }
+
+ public ArrayList getTest_packages() {
+ return test_packages;
+ }
+
+ public void setTest_packages(ArrayList test_packages) {
+ this.test_packages = test_packages;
+ }
+
+ public File getPath() {
+ return path;
+ }
+
+ public void setPath(File path) {
+ this.path = path;
+ }
+
+ public File getSrc() {
+ return src;
+ }
+
+ public void setSrc(File src) {
+ this.src = src;
+ }
+
+ public File getSrtc() {
+ return srtc;
+ }
+
+ public void setSrtc(File srtc) {
+ this.srtc = srtc;
+ }
+
+ public String getAbsolutePath() {
+ return absolutePath;
+ }
+
+ public void setAbsolutePath(String absolutePath) {
+ this.absolutePath = absolutePath;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public GroundhogASTVisitor getVisitor() {
+ return visitor;
+ }
+
+ public void setVisitor(GroundhogASTVisitor visitor) {
+ this.visitor = visitor;
+ }
+
+ public StatisticsTable getSt_code() {
+ return st_code;
+ }
+
+ public void setSt_code(StatisticsTable st_code) {
+ this.st_code = st_code;
+ }
+
+ public StatisticsTable getSt_test() {
+ return st_test;
+ }
+
+ public void setSt_test(StatisticsTable st_test) {
+ this.st_test = st_test;
+ }
+
+ public Statistics getStatistics() {
+ return statistics;
+ }
+
+ public void setStatistics(Statistics statistics) {
+ this.statistics = statistics;
+ }
+
+ public MetricsCollector getCollector() {
+ return collector;
+ }
+
+ public void setCollector(MetricsCollector collector) {
+ this.collector = collector;
+ }
+
+ public static String getDefaultSourceRootCode() {
+ return default_source_root_code;
+ }
+
+ @SerializedName("name")
+ private String name;
+
+ @Transient
+ private GroundhogASTVisitor visitor;
+
+ @Transient
+ private StatisticsTable st_code;
+
+ @Transient
+ private StatisticsTable st_test;
+
+ @Transient
+ private Statistics statistics = new Statistics();
+
+ @Transient
+ private MetricsCollector collector;
+
+ /**
+ * Default constructor used by morphia to create a empty object setting the annotated attributes using reflection
+ */
+ public JavaProject() {}
+
+ public JavaProject(File path, String name) throws InvalidJavaProjectPathException {
+
+ this.path = path;
+ this.name = name;
+ commonInit();
+ }
+
+ public JavaProject(File path) throws InvalidJavaProjectPathException{
+
+ this.path = path;
+ this.name = path.getName();
+ commonInit();
+ }
+
+ public JavaProject(String absolutePath, String name) throws InvalidJavaProjectPathException{
+
+ this.path = new File(absolutePath);
+ this.name = name;
+ commonInit();
+ }
+
+ public JavaProject(String path) throws InvalidJavaProjectPathException{
+
+ this.path = new File(path);
+ this.name = this.path.isDirectory() ? this.path.getName() : "";
+ commonInit();
+ }
+
+ private void commonInit() throws InvalidJavaProjectPathException{
+
+ checkPath();
+ this.absolutePath = this.path.getAbsolutePath();
+ this.collector = new MetricsCollector();
+ this.code_packages = new ArrayList();
+ this.test_packages = new ArrayList();
+ this.visitor = new GroundhogASTVisitor();
+ }
+
+ private void checkPath() throws InvalidJavaProjectPathException{
+
+ if(!this.path.isDirectory()){
+
+ logger.error("This project has an invalid path!");
+
+ throw new InvalidJavaProjectPathException();
+ }
+ }
+
+ public boolean generateStructure(String src, String srtc) throws InvalidJavaProjectPathException, InvalidSourceRootCodePathException, InvalidTestSourcePathException, InvalidJavaFileException{
+
+ if(this.path == null || !this.path.isDirectory())
+ return false;
+ else{
+ detectSourceRootCode(src);
+ detectSourceRootTestCode(srtc);
+ detectCodePackages();
+ detectTestCodePackages();
+ return true;
+ }
+ }
+
+ public boolean generateStructure(File src, File srtc) throws InvalidJavaProjectPathException, InvalidSourceRootCodePathException, InvalidTestSourcePathException, InvalidJavaFileException{
+
+ if(this.path == null || !this.path.isDirectory())
+ return false;
+ else{
+
+ detectSourceRootCode(src);
+ detectCodePackages();
+
+ if(srtc != null){
+ detectSourceRootTestCode(srtc);
+ detectTestCodePackages();
+ }
+
+ return true;
+ }
+ }
+
+ private void detectSourceRootCode(String source_root_code) throws InvalidJavaProjectPathException, InvalidSourceRootCodePathException{
+ logger.info("Detecting sorce root code...");
+ //This line has been commented because we need to decide how to detect the correct java source root code
+ //String scr = (source_root_code == null ? JavaProject.default_source_root_code : source_root_code);
+
+ File temp_src = null;
+ String src = source_root_code;
+
+ temp_src = new File(this.path.getAbsolutePath(), src);
+
+ detectSourceRootCode(temp_src);
+
+ }
+
+ private void detectSourceRootCode(File source_root_code) throws InvalidJavaProjectPathException, InvalidSourceRootCodePathException{
+
+ try{
+ if(source_root_code.exists())
+ this.src = source_root_code;
+ else
+ throw new InvalidSourceRootCodePathException();
+ }catch (NullPointerException e){
+ System.err.println("Source root code not found!");
+ }
+ }
+
+ private void detectSourceRootTestCode(String source_test_root_code) throws InvalidTestSourcePathException{
+ logger.info("Detecting sorce root test code...");
+
+ File temp_srtc = null;
+
+ temp_srtc = new File(this.path.getAbsolutePath(),source_test_root_code);
+
+ detectSourceRootTestCode(temp_srtc);
+ }
+
+ private void detectSourceRootTestCode(File source_test_root_code) throws InvalidTestSourcePathException{
+
+ try{
+ if(source_test_root_code.exists())
+ this.srtc = source_test_root_code;
+ else
+ throw new InvalidTestSourcePathException();
+ }catch (NullPointerException e){
+ System.err.println("Source root test code not found!");
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Name: " + this.name + "\n"
+ + "SRC: " + ((this.src == null) ? "not found\n" : (this.src.getAbsolutePath() + "\n"))
+ + "SRTC: " + ((this.srtc == null) ? "not found" : this.srtc.getAbsolutePath());
+ }
+
+ private void detectPackages(File dir,ArrayList packages, File src) throws InvalidJavaFileException{
+
+ //Check if this project have files on default package
+ if(dir.equals(this.src) && hasJavaFiles(dir)){
+ logger.debug("Package default detected!");
+ packages.add(new JavaPackage(dir,"default"));
+ }
+
+ for(File file : dir.listFiles()){
+ //We have a directory and java files, so we have a package
+ if(file.isDirectory() && hasJavaFiles(file)){
+ logger.debug("Package " + extractPackageName(src,file) + " detected!");
+ JavaPackage java_package = new JavaPackage(file,extractPackageName(src,file));
+ packages.add(java_package);
+ detectPackages(file,packages,src);
+ }else if(file.isDirectory()){
+ //Search for packages inside actual package
+ detectPackages(file,packages,src);
+ }
+ }
+
+ }
+
+ private void detectCodePackages() throws InvalidJavaFileException{
+ if(this.src != null){
+ detectPackages(this.src, this.code_packages, this.src);
+ }
+ }
+
+ private void detectTestCodePackages() throws InvalidJavaFileException{
+ if(this.srtc != null){
+ detectPackages(this.srtc, this.test_packages, this.srtc);
+ }
+ }
+
+ private boolean hasJavaFiles(File dir){
+
+ for (File file : dir.listFiles()){
+ if(file.getName().endsWith(".java")) return true;
+ }
+
+ return false;
+ }
+
+ private String extractPackageName(File src, File dir){
+ return dir.getAbsolutePath().
+ replace(src.getAbsolutePath()+File.separator, "")
+ .replaceAll(Matcher.quoteReplacement(File.separator), ".");
+ }
+
+ public boolean generateMetrics(boolean include_tests){
+
+ //For each code package of this project generate their metrics
+ for (JavaPackage _package : this.code_packages){
+ _package.generateMetrics(this.visitor, this.collector);
+ }
+
+ logger.info("All code packages done!");
+
+ if(include_tests){
+ for (JavaPackage _package : this.test_packages){
+ _package.generateMetrics(this.visitor,this.collector);
+ }
+ }
+
+ logger.info("All test packages done!");
+
+ return true;
+ }
+
+ public boolean generateMetrics(boolean include_tests, GroundhogDB db){
+
+ //For each code package of this project generate their metrics
+ for (JavaPackage _package : this.code_packages){
+ _package.generateMetrics(this.visitor, this.collector,db);
+ }
+
+ logger.info("All code packages done!");
+
+ if(include_tests){
+
+ for (JavaPackage _package : this.test_packages){
+ _package.generateMetrics(this.visitor,this.collector,db);
+ }
+
+ logger.info("All test packages done!");
+ }
+
+ db.save(this);
+
+ return true;
+ }
+}
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/MetricsCollector.java b/src/java/main/br/ufpe/cin/groundhog/metrics/MetricsCollector.java
new file mode 100644
index 0000000..e8f11d1
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/MetricsCollector.java
@@ -0,0 +1,135 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+public final class MetricsCollector {
+
+ private long max;
+ private double avg;
+ private long total;
+
+
+ private void process(Hashtable table, long fileCount){
+ long denominator = 0;
+ long numerator = 0;
+
+ for (Map.Entry map : table.entrySet()){
+ denominator += map.getValue();
+ numerator += (map.getKey() * map.getValue());
+ if(this.max < map.getKey()) this.max = map.getKey();
+ }
+
+ //This code activates the calculation of the avg of the pakages taking into account its files rather than its methods.
+ //if(fileCount > 1) this.avg = Util.safeCalculateAvg(numerator, fileCount);
+ //else this.avg = Util.safeCalculateAvg(numerator, denominator);
+
+ this.avg = Util.safeCalculateAvg(numerator, denominator);
+
+ this.total = numerator;
+ }
+
+ private void clear(){
+ this.max = 0;
+ this.avg = 0.0;
+ this.total = 0;
+ }
+
+ private void commonProcess(StatisticsTable table, Statistics stat){
+ clear();
+ process(stat.methodCall,stat.fileCount);
+ table.FOUT_avg = this.avg;
+ table.FOUT_max = this.max;
+ table.FOUT_sum = this.total;
+
+ clear();
+ process(stat.lineCounter,stat.fileCount);
+ table.MLOC_avg = this.avg;
+ table.MLOC_max = this.max;
+ table.MLOC_sum = this.total;
+
+ clear();
+ process(stat.depCounter,stat.fileCount);
+ table.NBD_avg = this.avg;
+ table.NBD_max = this.max;
+ table.NBD_sum = this.total;
+
+ clear();
+ process(stat.fieldCounter,stat.fileCount);
+ table.NOF_avg = this.avg;
+ table.NOF_max = this.max;
+ table.NOF_sum = this.total;
+
+ clear();
+ process(stat.sFieldCounter,stat.fileCount);
+ table.NSF_avg = this.avg;
+ table.NSF_max = this.max;
+ table.NSF_sum = this.total;
+
+ clear();
+ process(stat.methodCounter,stat.fileCount);
+ table.NOM_avg = this.avg;
+ table.NOM_max = this.max;
+ table.NOM_sum = this.total;
+
+ clear();
+ process(stat.sMethodCounter,stat.fileCount);
+ table.NSM_avg = this.avg;
+ table.NSM_max = this.max;
+ table.NSM_sum = this.total;
+
+ clear();
+ process(stat.parameters,stat.fileCount);
+ table.PAR_avg = this.avg;
+ table.PAR_max = this.max;
+ table.PAR_sum = this.total;
+
+ clear();
+ process(stat.cycloCounter,stat.fileCount);
+ table.VG_avg = this.avg;
+ table.VG_max = this.max;
+ table.VG_sum = this.total;
+ }
+
+ public void processFileLevel(StatisticsTableFile table, Statistics stat){
+
+ commonProcess(table, stat);
+ table.ACD = stat.anonymousClasses;
+ table.NOI = stat.interfaces;
+ table.NOT = stat.classes;
+ table.TLOC = stat.totalCode;
+ }
+
+ public void processPackageLevel(StatisticsTablePackage table, List stats){
+
+ //Join all statistics to obtain package level metrics
+ Statistics temp = new Statistics(true);
+ for (Statistics st : stats) {
+ temp.merge(st);
+ }
+
+ commonProcess(table, temp);
+
+ table.ACD_sum = temp.anonymousClasses;
+ table.ACD_max = temp.anonymousClasses_max;
+ table.ACD_avg = Util.safeCalculateAvg(temp.anonymousClasses, temp.fileCount);
+
+ table.NOI_sum = temp.interfaces;
+ table.NOI_max = temp.interfaces_max;
+ table.NOI_avg = Util.safeCalculateAvg(temp.interfaces, temp.fileCount);
+
+ table.NOT_sum = temp.classes;
+ table.NOT_max = temp.classes_max;
+ table.NOT_avg = Util.safeCalculateAvg(temp.classes, temp.fileCount);
+
+ table.TLOC_sum = temp.totalCode;
+ table.TLOC_max = temp.totalCode_max;
+ table.TLOC_avg = Util.safeCalculateAvg(temp.totalCode, temp.fileCount);
+
+ table.NOCU = temp.compilationUnits;
+
+ }
+
+}
+
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/Statistics.java b/src/java/main/br/ufpe/cin/groundhog/metrics/Statistics.java
new file mode 100644
index 0000000..f269b64
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/Statistics.java
@@ -0,0 +1,117 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import java.util.Hashtable;
+
+public class Statistics {
+ /*It's necessary to use final variables in order to interact with
+ * the code inside ASTVisitor class
+ */
+
+ /**
+ * Accumulators for method metrics
+ */
+ public Hashtable methodCall = new Hashtable();
+ public Hashtable lineCounter = new Hashtable();
+ public Hashtable depCounter = new Hashtable();
+ public Hashtable parameters = new Hashtable();
+ public Hashtable cycloCounter = new Hashtable();
+
+ /**
+ * Accumulators for classes metrics
+ */
+ public Hashtable fieldCounter = new Hashtable();
+ public Hashtable methodCounter = new Hashtable();
+ public Hashtable sFieldCounter = new Hashtable();
+ public Hashtable sMethodCounter = new Hashtable();
+
+ /**
+ * Accumulators for files metrics
+ */
+ public long anonymousClasses = 0;
+ public long anonymousClasses_max = 0;
+ public long interfaces = 0;
+ public long interfaces_max = 0;
+ public long classes = 0;
+ public long classes_max = 0;
+ public long totalCode = 0;
+ public long totalCode_max = 0;
+
+ /**
+ * Accumulators for package metrics
+ */
+ public long compilationUnits = 0;
+
+ /**
+ * Count of how many statistics this statistics represents
+ */
+ public long fileCount = 1;
+
+ public Statistics() {}
+
+ public Statistics(boolean Package){
+ this.fileCount = 0;
+ }
+
+ public void merge(Statistics statistics){
+ this.fileCount++;
+ this.methodCall = Util.mergeHashTable(this.methodCall, statistics.methodCall);
+ this.lineCounter = Util.mergeHashTable(this.lineCounter, statistics.lineCounter);
+ this.depCounter = Util.mergeHashTable(this.depCounter, statistics.depCounter);
+ this.parameters = Util.mergeHashTable(this.parameters, statistics.parameters);
+ this.cycloCounter = Util.mergeHashTable(this.cycloCounter, statistics.cycloCounter);
+ this.fieldCounter = Util.mergeHashTable(this.fieldCounter, statistics.fieldCounter);
+ this.methodCounter = Util.mergeHashTable(this.methodCounter, statistics.methodCounter);
+ this.sFieldCounter = Util.mergeHashTable(this.sFieldCounter, statistics.sFieldCounter);
+ this.sMethodCounter = Util.mergeHashTable(this.sMethodCounter, statistics.sMethodCounter);
+ this.anonymousClasses += statistics.anonymousClasses;
+ if(statistics.anonymousClasses > this.anonymousClasses_max) this.anonymousClasses_max = statistics.anonymousClasses;
+ this.interfaces += statistics.interfaces;
+ if(statistics.interfaces > this.interfaces_max) this.interfaces_max = statistics.interfaces;
+ this.classes += statistics.classes;
+ if(statistics.classes > this.classes_max) this.classes_max = statistics.classes;
+ this.totalCode += statistics.totalCode;
+ if(statistics.totalCode > this.totalCode_max) this.totalCode_max = statistics.totalCode;
+ this.compilationUnits += statistics.compilationUnits;
+ }
+
+ public void clear() {
+ this.methodCall.clear();
+ this.lineCounter.clear();
+ this.depCounter.clear();
+ this.parameters.clear();
+ this.cycloCounter.clear();
+ this.fieldCounter.clear();
+ this.methodCounter.clear();
+ this.sFieldCounter.clear();
+ this.sMethodCounter.clear();
+ this.anonymousClasses = 0;
+ this.anonymousClasses_max = 0;
+ this.interfaces = 0;
+ this.interfaces_max = 0;
+ this.classes = 0;
+ this.classes_max = 0;
+ this.totalCode = 0;
+ this.totalCode_max = 0;
+ this.compilationUnits = 0;
+ }
+
+ @Override
+ public String toString() {
+ return "FOUT: " + methodCall + "\n" +
+ "MLOC: " + lineCounter + "\n" +
+ "NBD: " + depCounter + "\n" +
+ "PAR: " + parameters + "\n" +
+ "VG: " + cycloCounter + "\n" +
+
+ "NOF: " + fieldCounter + "\n" +
+ "NOM: " + methodCounter + "\n" +
+ "NSF: " + sFieldCounter + "\n" +
+ "NSM: " + sMethodCounter + "\n" +
+
+ "ACD: " + anonymousClasses + "\n" +
+ "NOI: " + interfaces + "\n" +
+ "NOT: " + classes + "\n" +
+ "TLOC: " + totalCode + "\n" +
+ "NOCU: " + compilationUnits;
+ }
+}
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/StatisticsTable.java b/src/java/main/br/ufpe/cin/groundhog/metrics/StatisticsTable.java
new file mode 100644
index 0000000..61ac5db
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/StatisticsTable.java
@@ -0,0 +1,103 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import com.google.gson.annotations.SerializedName;
+
+public abstract class StatisticsTable {
+
+ //Values for file level
+ @SerializedName("metric_fout_avg")
+ public double FOUT_avg;
+ @SerializedName("metric_fout_max")
+ public long FOUT_max;
+ @SerializedName("metric_fout_sum")
+ public long FOUT_sum;
+
+ @SerializedName("metric_mloc_avg")
+ public double MLOC_avg;
+ @SerializedName("metric_mloc_max")
+ public long MLOC_max;
+ @SerializedName("metric_mloc_sum")
+ public long MLOC_sum;
+
+ @SerializedName("metric_nbd_avg")
+ public double NBD_avg;
+ @SerializedName("metric_nbd_max")
+ public long NBD_max;
+ @SerializedName("metric_nbd_sum")
+ public long NBD_sum;
+
+ @SerializedName("metric_nof_avg")
+ public double NOF_avg;
+ @SerializedName("metric_nof_max")
+ public long NOF_max;
+ @SerializedName("metric_nof_sum")
+ public long NOF_sum;
+
+ @SerializedName("metric_nom_avg")
+ public double NOM_avg;
+ @SerializedName("metric_nom_max")
+ public long NOM_max;
+ @SerializedName("metric_nom_sum")
+ public long NOM_sum;
+
+ @SerializedName("metric_nsf_avg")
+ public double NSF_avg;
+ @SerializedName("metric_nsf_max")
+ public long NSF_max;
+ @SerializedName("metric_nsf_sum")
+ public long NSF_sum;
+
+ @SerializedName("metric_nsm_avg")
+ public double NSM_avg;
+ @SerializedName("metric_nsm_max")
+ public long NSM_max;
+ @SerializedName("metric_nsm_sum")
+ public long NSM_sum;
+
+ @SerializedName("metric_par_avg")
+ public double PAR_avg;
+ @SerializedName("metric_par_max")
+ public long PAR_max;
+ @SerializedName("metric_par_sum")
+ public long PAR_sum;
+
+ @SerializedName("metric_vg_avg")
+ public double VG_avg;
+ @SerializedName("metric_vg_max")
+ public long VG_max;
+ @SerializedName("metric_vg_sum")
+ public long VG_sum;
+
+ @Override
+ public String toString() {
+ return
+ "metric_fout_avg: " + FOUT_avg + "\n"+
+ "metric_fout_max: " + FOUT_max + "\n"+
+ "metric_fout_sum: " + FOUT_sum + "\n"+
+ "metric_mloc_avg: " + MLOC_avg + "\n"+
+ "metric_mloc_max: " + MLOC_max + "\n"+
+ "metric_mloc_sum: " + MLOC_sum + "\n"+
+ "metric_nbd_avg: " + NBD_avg + "\n"+
+ "metric_nbd_max: " + NBD_max + "\n"+
+ "metric_nbd_sum: " + NBD_sum + "\n"+
+ "metric_nof_avg: " + NOF_avg + "\n"+
+ "metric_nof_max: " + NOF_max + "\n"+
+ "metric_nof_sum: " + NOF_sum + "\n"+
+ "metric_nom_avg: " + NOM_avg + "\n"+
+ "metric_nom_max: " + NOM_max + "\n"+
+ "metric_nom_sum: " + NOM_sum + "\n"+
+ "metric_nsf_avg: " + NSF_avg + "\n"+
+ "metric_nsf_max: " + NSF_max + "\n"+
+ "metric_nsf_sum: " + NSF_sum + "\n"+
+ "metric_nsm_avg: " + NSM_avg + "\n"+
+ "metric_nsm_max: " + NSM_max + "\n"+
+ "metric_nsm_sum: " + NSM_sum + "\n"+
+ "metric_par_avg: " + PAR_avg + "\n"+
+ "metric_par_max: " + PAR_max + "\n"+
+ "metric_par_sum: " + PAR_sum + "\n"+
+ "metric_vg_avg: " + VG_avg + "\n"+
+ "metric_vg_max: " + VG_max + "\n"+
+ "metric_vg_sum: " + VG_sum + "\n";
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/StatisticsTableFile.java b/src/java/main/br/ufpe/cin/groundhog/metrics/StatisticsTableFile.java
new file mode 100644
index 0000000..cedeb58
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/StatisticsTableFile.java
@@ -0,0 +1,37 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import org.bson.types.ObjectId;
+import org.mongodb.morphia.annotations.Entity;
+import org.mongodb.morphia.annotations.Id;
+import org.mongodb.morphia.annotations.Indexed;
+
+import com.google.gson.annotations.SerializedName;
+
+@Entity("statisticstablefile")
+public class StatisticsTableFile extends StatisticsTable{
+
+ @Id
+ @Indexed(unique=true, dropDups=true)
+ ObjectId id;
+
+ @SerializedName("metric_acd")
+ public long ACD;
+
+ @SerializedName("metric_noi")
+ public long NOI;
+
+ @SerializedName("metric_not")
+ public long NOT;
+
+ @SerializedName("metric_tloc")
+ public long TLOC;
+
+ @Override
+ public String toString() {
+ return super.toString() +
+ "metric_acd: " + ACD + "\n" +
+ "metric_noi: " + NOI + "\n" +
+ "metric_not: " + NOT + "\n" +
+ "metric_tloc: " + TLOC;
+ }
+}
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/StatisticsTablePackage.java b/src/java/main/br/ufpe/cin/groundhog/metrics/StatisticsTablePackage.java
new file mode 100644
index 0000000..886cb5b
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/StatisticsTablePackage.java
@@ -0,0 +1,66 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import org.bson.types.ObjectId;
+import org.mongodb.morphia.annotations.Entity;
+import org.mongodb.morphia.annotations.Id;
+import org.mongodb.morphia.annotations.Indexed;
+
+import com.google.gson.annotations.SerializedName;
+
+@Entity("statisticstablepackage")
+public class StatisticsTablePackage extends StatisticsTable{
+
+ @Id
+ @Indexed(unique=true, dropDups=true)
+ ObjectId id;
+
+ @SerializedName("metric_nocu")
+ public long NOCU;
+
+ @SerializedName("metric_acd_avg")
+ public double ACD_avg;
+ @SerializedName("metric_acd_max")
+ public long ACD_max;
+ @SerializedName("metric_acd_sum")
+ public long ACD_sum;
+
+ @SerializedName("metric_noi_avg")
+ public double NOI_avg;
+ @SerializedName("metric_noi_max")
+ public long NOI_max;
+ @SerializedName("metric_noi_sum")
+ public long NOI_sum;
+
+ @SerializedName("metric_not_avg")
+ public double NOT_avg;
+ @SerializedName("metric_not_max")
+ public long NOT_max;
+ @SerializedName("metric_not_sum")
+ public long NOT_sum;
+
+ @SerializedName("metric_tloc_avg")
+ public double TLOC_avg;
+ @SerializedName("metric_tloc_max")
+ public long TLOC_max;
+ @SerializedName("metric_tloc_sum")
+ public long TLOC_sum;
+
+ @Override
+ public String toString() {
+ return super.toString() +
+ "metric_acd_avg: " + ACD_avg + "\n" +
+ "metric_acd_max: " + ACD_max + "\n" +
+ "metric_acd_sum: " + ACD_sum + "\n" +
+ "metric_noi_avg: " + NOI_avg + "\n" +
+ "metric_noi_max: " + NOI_max + "\n" +
+ "metric_noi_sum: " + NOI_sum + "\n" +
+ "metric_not_avg: " + NOT_avg + "\n" +
+ "metric_not_max: " + NOT_max + "\n" +
+ "metric_not_sum: " + NOT_sum + "\n" +
+ "metric_tloc_avg: " + TLOC_avg + "\n" +
+ "metric_tloc_max: " + TLOC_max + "\n" +
+ "metric_tloc_sum: " + TLOC_sum + "\n" +
+ "metric_nocu: " + NOCU;
+ }
+
+}
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/Test.java b/src/java/main/br/ufpe/cin/groundhog/metrics/Test.java
new file mode 100644
index 0000000..3ec1760
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/Test.java
@@ -0,0 +1,155 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import java.io.*;
+import java.util.Hashtable;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.dom.*;
+
+public class Test {
+
+ public static final String VERSION_1_4 = "1.4";
+ public static final String VERSION_1_5 = "1.5";
+ public static final String VERSION_1_6 = "1.6";
+ public static final String VERSION_1_7 = "1.7";
+
+ private static final Set ALLOWED_TARGET_JDKS = new LinkedHashSet();
+ static {
+ ALLOWED_TARGET_JDKS.add(VERSION_1_4);
+ ALLOWED_TARGET_JDKS.add(VERSION_1_5);
+ ALLOWED_TARGET_JDKS.add(VERSION_1_6);
+ ALLOWED_TARGET_JDKS.add(VERSION_1_7);
+ }
+
+ private static final Logger log = Logger.getLogger(Test.class);
+ public static boolean DEBUG;
+
+ private String targetJdk = VERSION_1_4;
+ private String encoding = "UTF-8";
+
+ public void setTargetJdk( String targetJdk ) {
+ if(!ALLOWED_TARGET_JDKS.contains(targetJdk))
+ throw new IllegalArgumentException("Invalid value for targetJdk: [" + targetJdk + "]. Allowed are "+ALLOWED_TARGET_JDKS);
+
+ this.targetJdk = targetJdk;
+ }
+
+ public void setEncoding( String encoding ) {
+ if( encoding == null )
+ throw new IllegalArgumentException("encoding is null");
+ if( encoding.trim().length() == 0 )
+ throw new IllegalArgumentException("encoding is empty");
+ this.encoding = encoding;
+ }
+
+ public GroundhogASTVisitor visitFile( File file ) throws IOException {
+ if(!file.exists())
+ new IllegalArgumentException("File "+file.getAbsolutePath()+" doesn't exist");
+
+ String source = readFileToString( file, encoding );
+
+ return visitString( source );
+ }
+
+ public static String readFileToString( File file, String encoding ) throws IOException {
+ FileInputStream stream = new FileInputStream( file );
+ String result = null;
+ try {
+ result = readInputStreamToString( stream, encoding );
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ return result;
+ }
+
+ public GroundhogASTVisitor visit( InputStream stream, String encoding ) throws IOException {
+ if( stream == null )
+ throw new IllegalArgumentException("stream is null");
+ if( encoding == null )
+ throw new IllegalArgumentException("encoding is null");
+ if( encoding.trim().length() == 0 )
+ throw new IllegalArgumentException("encoding is empty");
+
+ String source = readInputStreamToString( stream, encoding );
+
+ return visitString( source );
+ }
+
+ public static String readInputStreamToString( InputStream stream, String encoding ) throws IOException {
+
+ Reader r = new BufferedReader( new InputStreamReader( stream, encoding ), 16384 );
+ StringBuilder result = new StringBuilder(16384);
+ char[] buffer = new char[16384];
+
+ int len;
+ while((len = r.read( buffer, 0, buffer.length )) >= 0) {
+ result.append(buffer, 0, len);
+ }
+
+ return result.toString();
+ }
+
+ public GroundhogASTVisitor visitString( String source ) {
+ ASTParser parser = ASTParser.newParser(AST.JLS3);
+
+ @SuppressWarnings( "unchecked" )
+ Map options = JavaCore.getOptions();
+ if(VERSION_1_5.equals(targetJdk))
+ JavaCore.setComplianceOptions(JavaCore.VERSION_1_5, options);
+ else if(VERSION_1_6.equals(targetJdk))
+ JavaCore.setComplianceOptions(JavaCore.VERSION_1_6, options);
+ else if(VERSION_1_7.equals(targetJdk))
+ JavaCore.setComplianceOptions(JavaCore.VERSION_1_7, options);
+ else {
+ if(!VERSION_1_4.equals(targetJdk)) {
+ log.warn("Unknown targetJdk ["+targetJdk+"]. Using "+VERSION_1_4+" for parsing. Supported values are: "
+ + VERSION_1_4 + ", "
+ + VERSION_1_5 + ", "
+ + VERSION_1_6
+ );
+ }
+ JavaCore.setComplianceOptions(JavaCore.VERSION_1_4, options);
+ }
+ parser.setCompilerOptions(options);
+
+ parser.setResolveBindings(false);
+ parser.setStatementsRecovery(false);
+ parser.setBindingsRecovery(false);
+ parser.setSource(source.toCharArray());
+ //parser.setIgnoreMethodBodies(false);
+
+ CompilationUnit ast = (CompilationUnit) parser.createAST(null);
+
+ // AstVisitor extends org.eclipse.jdt.core.dom.ASTVisitor
+ GroundhogASTVisitor visitor = new GroundhogASTVisitor();
+ Statistics statistics = new Statistics();
+ visitor.setStatistics(statistics);
+ ast.accept( visitor );
+
+ return visitor;
+ }
+
+ public static void main(String []args) throws IOException{
+ System.out.println("Vai começar!");
+ Test test = new Test();
+ File file = new File("/home/bruno/scm/github.com/groundhog2/src/java/main/br/ufpe/cin/groundhog/metrics/Test3.java");
+ if (file.isFile()){
+ GroundhogASTVisitor visitor = test.visitFile(file);
+ visitor.toString();
+ System.out.println(visitor.getStatistics());
+ }else{
+ System.out.println("Is not a file!");
+ }
+
+ Hashtable table = new Hashtable();
+
+ }
+}
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/Test3.java b/src/java/main/br/ufpe/cin/groundhog/metrics/Test3.java
new file mode 100644
index 0000000..dedf81f
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/Test3.java
@@ -0,0 +1,96 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import br.ufpe.cin.groundhog.extractor.GitCommitExtractor;
+
+public class Test3 {
+
+ enum lol {
+
+ }
+
+ public void zoeira1(String k, String i, String j){
+ System.out.println("HAHAHAHAH");
+ System.out.println("HAHAHAHAH");
+ System.out.println("HAHAHAHAH");
+ System.out.println("HAHAHAHAH");
+ System.out.println("HAHAHAHAH");
+ }
+
+ public void zoeira(String ki, String i){
+ try {
+ int k = 0;
+ synchronized (this) {
+ do{
+ System.out.println("Testando, testando, testando, tetetetetestando!");
+
+ ArrayList arr = new ArrayList(){
+
+ @Override
+ public String toString() {
+
+ int nnumber = 10;
+
+ while(nnumber != 0){
+
+ try {
+
+ super.toString();
+ nnumber--;
+ } catch (ArrayIndexOutOfBoundsException e){
+ if(nnumber == 0){
+ System.out.println("Zoeira never ends");
+ }else{
+ System.out.println("kkkkkk");
+ }
+ } catch (NullPointerException e){
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ }
+ return super.toString();
+
+ }
+ };
+ }while(k++<10);
+ }
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ System.out.println("Testando, testando, testando, tetetetetestando!");
+ System.out.println("Testando, testando, testando, tetetetetestando!");
+ System.out.println("Testando, testando, testando, tetetetetestando!");
+ System.out.println("Testando, testando, testando, tetetetetestando!");
+// System.out.println("Testando, testando, testando, tetetetetestando!");
+// System.out.println("Testando, testando, testando, tetetetetestando!");
+// System.out.println("Testando, testando, testando, tetetetetestando!");
+// System.out.println("Testando, testando, testando, tetetetetestando!");
+// System.out.println("Testando, testando, testando, tetetetetestando!");
+// System.out.println("Testando, testando, testando, tetetetetestando!");
+// System.out.println("Testando, testando, testando, tetetetetestando!");
+// System.out.println("Testando, testando, testando, tetetetetestando!");
+// System.out.println("Testando, testando, testando, tetetetetestando!");
+// System.out.println("Testando, testando, testando, tetetetetestando!");
+// System.out.println("Testando, testando, testando, tetetetetestando!");
+ }
+
+ public void zoeira2(String k, String i,String ki, String ii){
+ if(true){
+ if(true){
+ System.out.println("Testando, testando, testando, tetetetetestando!");
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ GitCommitExtractor extractor = new GitCommitExtractor();
+ File file = new File("/home/bruno/scm/github.com/learnhaskell");
+ if(file.isDirectory()){
+ extractor.extractCommits(file);
+ extractor.extractCommits(file);
+ }
+
+ }
+}
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/Teste2.java b/src/java/main/br/ufpe/cin/groundhog/metrics/Teste2.java
new file mode 100644
index 0000000..9595d2e
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/Teste2.java
@@ -0,0 +1,25 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import java.net.UnknownHostException;
+
+import br.ufpe.cin.groundhog.database.GroundhogDB;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidJavaFileException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidJavaProjectPathException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidSourceRootCodePathException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidTestSourcePathException;
+
+public class Teste2 {
+
+ public static void main(String[] args) throws InvalidJavaProjectPathException, InvalidSourceRootCodePathException, InvalidTestSourcePathException, InvalidJavaFileException, UnknownHostException {
+ GroundhogDB ghdb = new GroundhogDB("127.0.0.1", "java_metrics");
+ ghdb.getMapper().mapPackage("br.ufpe.cin.groundhog.metrics");
+
+ JavaFile j = new JavaFile("oi");
+ JavaProject project = new JavaProject("src/main/resources/scribe-java/");
+ project.generateStructure("src/main", "src/test");
+ System.out.println("Scanning packages to project:");
+ System.out.println(project.toString());
+ System.out.println("################################################");
+ project.generateMetrics(true,ghdb);
+ }
+}
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/TesteMongoDB.java b/src/java/main/br/ufpe/cin/groundhog/metrics/TesteMongoDB.java
new file mode 100644
index 0000000..0e3be88
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/TesteMongoDB.java
@@ -0,0 +1,42 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import java.net.UnknownHostException;
+import java.util.List;
+
+import org.mongodb.morphia.Key;
+
+import br.ufpe.cin.groundhog.database.GroundhogDB;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidJavaFileException;
+
+import com.mongodb.DB;
+import com.mongodb.DBObject;
+
+public class TesteMongoDB {
+
+ public static void main(String[] args) throws UnknownHostException, InvalidJavaFileException {
+// String dbName = "java_metrics";
+// MongoClient client = new MongoClient("127.0.0.1");
+// Morphia morphia = new Morphia();
+// Datastore datastore = morphia.createDatastore(client, dbName);
+ //DB db = ghdb.getMongo().getDB("java_metrics");
+
+ GroundhogDB ghdb = new GroundhogDB("127.0.0.1", "java_metrics");
+ ghdb.getMapper().mapPackage("br.ufpe.cin.groundhog.metrics");
+
+ JavaFile file = new JavaFile("/home/bruno/scm/github.com/groundhog2/src/java/main/br/ufpe/cin/groundhog/metrics/JavaFile.java");
+ JavaFile file2 = new JavaFile("/home/bruno/scm/github.com/groundhog2/src/java/main/br/ufpe/cin/groundhog/metrics/JavaPackage.java");
+ StatisticsTableFile table = new StatisticsTableFile();
+// DBObject object = ghdb.getMapper().toDBObject(file);
+ //DBObject object2 = ghdb.getMapper().toDBObject(file2);
+// System.out.println(db.getCollection("files").save(object));
+
+ Key key_f = ghdb.save(table);
+
+ file2.setTable(table);
+
+ Key key_jf = ghdb.save(file2);
+ System.out.println(key_jf);
+
+
+ }
+}
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/Util.java b/src/java/main/br/ufpe/cin/groundhog/metrics/Util.java
new file mode 100644
index 0000000..f54d834
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/Util.java
@@ -0,0 +1,108 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Stack;
+
+import org.eclipse.jdt.core.ToolFactory;
+import org.eclipse.jdt.core.compiler.IScanner;
+import org.eclipse.jdt.core.compiler.ITerminalSymbols;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+
+public class Util {
+
+ /**
+ * Merge Hashtable ht2 onto ht1
+ * @param ht1
+ * @param ht2
+ */
+ public static Hashtable mergeHashTable(Hashtable ht1, Hashtable ht2){
+ for (Map.Entry map : ht2.entrySet()){
+ if(ht1.containsKey(map.getKey())){
+ Util.safeAddToHashTable(ht1, map.getKey(), map.getValue());
+ }else{
+ ht1.put(map.getKey(), map.getValue());
+ }
+ }
+
+ return ht1;
+ }
+
+ public static void safeAddToHashTable(Hashtable table,int position){
+
+ if(table.containsKey(position)){
+ table.put(position, table.get(position)+1);
+ }else{
+ table.put(position, 1);
+ }
+ }
+
+ public static void safeAddToHashTable(Hashtable table, int key, int value){
+
+ if(table.containsKey(key)){
+ table.put(key, table.get(key)+value);
+ }else{
+ table.put(key, value);
+ }
+ }
+
+ /**
+ * Safe add the passed value to the top element of a stack
+ * @param stack
+ * @param value
+ * @return
+ */
+ public static int safeAddStackTop(Stack stack, int value){
+
+ int to_return = 0;
+
+ if(!stack.empty()){
+ to_return = stack.pop();
+ stack.push(to_return+value);
+ }
+
+ return to_return;
+ }
+
+
+ public static int countCodeLines(String source){
+ String temp = source.trim();
+ //Because we can get many tokens from the same line and JDT compiler removes all
+ //space, comment and line break in scanner, we need to create a Set to unique store
+ //the line number of tokens and get total of line codes
+ HashSet set = new HashSet<>();
+ //We need to process the file without whiteSpace and Commenst, but with the rest
+ IScanner scanner = ToolFactory.createScanner(false,false,true,true);
+ scanner.setSource(temp.toCharArray());
+ int token = 0x00;
+
+ //While don't reach the end of file count the number of lines
+ try {
+
+ do{
+
+ //Get the next token
+ token = scanner.getNextToken();
+ //And them process your line number
+ set.add(new Integer(scanner.getLineNumber(scanner.getCurrentTokenStartPosition())));
+
+ }while(token != ITerminalSymbols.TokenNameEOF);
+ } catch (InvalidInputException e) {
+ return 0;
+ }
+ return set.size();
+ }
+
+ public static double safeCalculateAvg(long numerator, long denominator){
+
+ BigDecimal bNumerator = new BigDecimal(numerator);
+ BigDecimal bDenominator = new BigDecimal(denominator);
+
+ if (denominator !=0) return bNumerator.divide(bDenominator,10,RoundingMode.HALF_EVEN).doubleValue();
+ else return 0;
+ }
+
+}
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/exception/InvalidJavaFileException.java b/src/java/main/br/ufpe/cin/groundhog/metrics/exception/InvalidJavaFileException.java
new file mode 100644
index 0000000..61ba52f
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/exception/InvalidJavaFileException.java
@@ -0,0 +1,15 @@
+package br.ufpe.cin.groundhog.metrics.exception;
+
+import br.ufpe.cin.groundhog.GroundhogException;
+
+public class InvalidJavaFileException extends GroundhogException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -7197149220798206965L;
+ private static final String message = "Invalid Java File path\nPlease check you project structure";
+
+ public InvalidJavaFileException() { super(InvalidJavaFileException.message); }
+ public InvalidJavaFileException(String message, Throwable cause) { super(InvalidJavaFileException.message, cause); }
+}
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/exception/InvalidJavaProjectPathException.java b/src/java/main/br/ufpe/cin/groundhog/metrics/exception/InvalidJavaProjectPathException.java
new file mode 100644
index 0000000..0ff3b86
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/exception/InvalidJavaProjectPathException.java
@@ -0,0 +1,18 @@
+package br.ufpe.cin.groundhog.metrics.exception;
+
+import br.ufpe.cin.groundhog.GroundhogException;
+
+public class InvalidJavaProjectPathException extends GroundhogException {
+
+ /**
+ * If an invalid Java path has passed this exception will be raised
+ * @author Bruno Soares
+ * @since 0.1.0
+ */
+
+ private static final long serialVersionUID = 7505823601337916084L;
+ private static final String message = "Invalid Java project path";
+
+ public InvalidJavaProjectPathException() { super(InvalidJavaProjectPathException.message); }
+ public InvalidJavaProjectPathException(String message, Throwable cause) { super(InvalidJavaProjectPathException.message, cause); }
+}
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/exception/InvalidSourceRootCodePathException.java b/src/java/main/br/ufpe/cin/groundhog/metrics/exception/InvalidSourceRootCodePathException.java
new file mode 100644
index 0000000..26a261a
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/exception/InvalidSourceRootCodePathException.java
@@ -0,0 +1,19 @@
+package br.ufpe.cin.groundhog.metrics.exception;
+
+import br.ufpe.cin.groundhog.GroundhogException;
+
+public class InvalidSourceRootCodePathException extends GroundhogException {
+
+ /**
+ * If an invalid Java path has passed this exception will be raised
+ * @author Bruno Soares
+ * @since 0.1.0
+ */
+
+ private static final long serialVersionUID = 476505897031339694L;
+ private static final String message = "Invalid source root code path";
+
+ public InvalidSourceRootCodePathException() { super(InvalidSourceRootCodePathException.message); }
+ public InvalidSourceRootCodePathException(String message, Throwable cause) { super(InvalidSourceRootCodePathException.message, cause); }
+
+}
diff --git a/src/java/main/br/ufpe/cin/groundhog/metrics/exception/InvalidTestSourcePathException.java b/src/java/main/br/ufpe/cin/groundhog/metrics/exception/InvalidTestSourcePathException.java
new file mode 100644
index 0000000..26360c8
--- /dev/null
+++ b/src/java/main/br/ufpe/cin/groundhog/metrics/exception/InvalidTestSourcePathException.java
@@ -0,0 +1,18 @@
+package br.ufpe.cin.groundhog.metrics.exception;
+
+import br.ufpe.cin.groundhog.GroundhogException;
+
+public class InvalidTestSourcePathException extends GroundhogException{
+
+ /**
+ * If an invalid Java path has passed this exception will be raised
+ * @author Bruno Soares
+ * @since 0.1.0
+ */
+
+ private static final long serialVersionUID = 2361880567057134357L;
+ private static final String message = "Invalid test source root code";
+
+ public InvalidTestSourcePathException() { super(InvalidTestSourcePathException.message); }
+ public InvalidTestSourcePathException(String message, Throwable cause) { super(InvalidTestSourcePathException.message, cause); }
+}
diff --git a/src/java/test/br/ufpe/cin/groundhog/metrics/GenerateMetricsWithoutPersistenceTest.java b/src/java/test/br/ufpe/cin/groundhog/metrics/GenerateMetricsWithoutPersistenceTest.java
new file mode 100644
index 0000000..751636d
--- /dev/null
+++ b/src/java/test/br/ufpe/cin/groundhog/metrics/GenerateMetricsWithoutPersistenceTest.java
@@ -0,0 +1,30 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import br.ufpe.cin.groundhog.metrics.exception.InvalidJavaFileException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidJavaProjectPathException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidSourceRootCodePathException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidTestSourcePathException;
+
+public class GenerateMetricsWithoutPersistenceTest {
+
+ @Test
+ public void test() {
+ try {
+ JavaProject project = new JavaProject("src/main/resources/scribe-java-project/");
+ project.generateStructure("src/main/", "src/test/");
+ project.generateMetrics(false);
+ long linesOfCode = 0;
+ for (JavaPackage table : project.getCode_packages()){
+ linesOfCode += table.getTable().TLOC_sum;
+ }
+ assertEquals("There should be 2808 lines of code in the source mais code", 2808, linesOfCode);
+ } catch (InvalidJavaProjectPathException | InvalidSourceRootCodePathException | InvalidTestSourcePathException | InvalidJavaFileException e) {
+ fail("An exception has occurred!");
+ }
+ }
+
+}
diff --git a/src/java/test/br/ufpe/cin/groundhog/metrics/InvalidJavaFileExceptionTest.java b/src/java/test/br/ufpe/cin/groundhog/metrics/InvalidJavaFileExceptionTest.java
new file mode 100644
index 0000000..e885728
--- /dev/null
+++ b/src/java/test/br/ufpe/cin/groundhog/metrics/InvalidJavaFileExceptionTest.java
@@ -0,0 +1,22 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import static org.junit.Assert.*;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import org.junit.Test;
+
+import br.ufpe.cin.groundhog.metrics.exception.InvalidJavaFileException;
+
+public class InvalidJavaFileExceptionTest {
+
+ @Test
+ public void testInvalidJavaFileException() {
+ try {
+ new JavaFile("invalid/path/");
+ fail("Should have thrown an InvalidJavaFileException because the java file path is invalid!");
+ } catch (InvalidJavaFileException e) {
+ assertThat(e.getMessage(), containsString("Invalid Java File path\nPlease check you project structure"));
+ }
+ }
+
+}
diff --git a/src/java/test/br/ufpe/cin/groundhog/metrics/InvalidJavaProjectPathExceptionTest.java b/src/java/test/br/ufpe/cin/groundhog/metrics/InvalidJavaProjectPathExceptionTest.java
new file mode 100644
index 0000000..b51ed72
--- /dev/null
+++ b/src/java/test/br/ufpe/cin/groundhog/metrics/InvalidJavaProjectPathExceptionTest.java
@@ -0,0 +1,22 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import org.junit.Test;
+
+import br.ufpe.cin.groundhog.metrics.exception.InvalidJavaProjectPathException;
+
+public class InvalidJavaProjectPathExceptionTest {
+
+ @Test
+ public void testInvalidJavaProjectPathException() {
+ try {
+ new JavaProject("/invalid/path/");
+ fail("Should have thrown an InvalidJavaProjectPathException because the project path is invalid!");
+ }catch(InvalidJavaProjectPathException e) {
+ assertThat(e.getMessage(), containsString("Invalid Java project path"));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/test/br/ufpe/cin/groundhog/metrics/InvalidSourceRootCodePathExceptionTest.java b/src/java/test/br/ufpe/cin/groundhog/metrics/InvalidSourceRootCodePathExceptionTest.java
new file mode 100644
index 0000000..7714965
--- /dev/null
+++ b/src/java/test/br/ufpe/cin/groundhog/metrics/InvalidSourceRootCodePathExceptionTest.java
@@ -0,0 +1,32 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import org.junit.Test;
+
+import br.ufpe.cin.groundhog.metrics.exception.InvalidJavaFileException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidJavaProjectPathException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidSourceRootCodePathException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidTestSourcePathException;
+
+public class InvalidSourceRootCodePathExceptionTest {
+
+ @Test
+ public void testInvalidSourceRootCodePathException() {
+ try {
+ JavaProject jp = new JavaProject("src/main/resources/scribe-java-project/");
+ jp.generateStructure("invalid/path/", "src/test/");
+ fail("Should have thrown an InvalidSourceRootCodePathException because the source root code path is invalid!");
+ }catch(InvalidSourceRootCodePathException e) {
+ assertThat(e.getMessage(), containsString("Invalid source root code path"));
+ } catch (InvalidJavaProjectPathException e) {
+ fail("Should have thrown an InvalidSourceRootCodePathException, but another exception was thrown!");
+ } catch (InvalidTestSourcePathException e) {
+ fail("Should have thrown an InvalidSourceRootCodePathException, but another exception was thrown!");
+ } catch (InvalidJavaFileException e) {
+ fail("Should have thrown an InvalidSourceRootCodePathException, but another exception was thrown!");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/test/br/ufpe/cin/groundhog/metrics/InvalidTestSourcePathExceptionTest.java b/src/java/test/br/ufpe/cin/groundhog/metrics/InvalidTestSourcePathExceptionTest.java
new file mode 100644
index 0000000..6e1fd86
--- /dev/null
+++ b/src/java/test/br/ufpe/cin/groundhog/metrics/InvalidTestSourcePathExceptionTest.java
@@ -0,0 +1,32 @@
+package br.ufpe.cin.groundhog.metrics;
+
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import org.junit.Test;
+
+import br.ufpe.cin.groundhog.metrics.exception.InvalidJavaFileException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidJavaProjectPathException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidSourceRootCodePathException;
+import br.ufpe.cin.groundhog.metrics.exception.InvalidTestSourcePathException;
+
+public class InvalidTestSourcePathExceptionTest {
+
+ @Test
+ public void testInvalidTestSourcePathException() {
+ try {
+ JavaProject jp = new JavaProject("src/main/resources/scribe-java-project/");
+ jp.generateStructure("src/main/", "invalid/path/");
+ fail("Should have thrown an InvalidTestSourcePathException because the test path is invalid!");
+ }catch(InvalidTestSourcePathException e) {
+ assertThat(e.getMessage(), containsString("Invalid test source root code"));
+ } catch (InvalidJavaProjectPathException e) {
+ fail("Should have thrown an InvalidTestSourcePathException, but another exception was thrown!");
+ } catch (InvalidSourceRootCodePathException e) {
+ fail("Should have thrown an InvalidTestSourcePathException, but another exception was thrown!");
+ } catch (InvalidJavaFileException e) {
+ fail("Should have thrown an InvalidTestSourcePathException, but another exception was thrown!");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/scribe-java-project/src/main/config/scribe-eclipse-formatter.xml b/src/main/resources/scribe-java-project/src/main/config/scribe-eclipse-formatter.xml
new file mode 100644
index 0000000..8ea5bc9
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/config/scribe-eclipse-formatter.xml
@@ -0,0 +1,290 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/scribe-java-project/src/main/config/scribe-eclipse.importorder b/src/main/resources/scribe-java-project/src/main/config/scribe-eclipse.importorder
new file mode 100644
index 0000000..1fcaf0f
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/config/scribe-eclipse.importorder
@@ -0,0 +1,7 @@
+#Organize Import Order
+#Tue Feb 21 20:29:55 GMT 2012
+4=java
+3=javax
+2=org
+1=org.boncey
+0=com
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/ServiceBuilder.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/ServiceBuilder.java
new file mode 100644
index 0000000..27f3c8f
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/ServiceBuilder.java
@@ -0,0 +1,169 @@
+package org.scribe.builder;
+
+import java.io.*;
+import org.scribe.builder.api.*;
+import org.scribe.exceptions.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+import org.scribe.utils.*;
+
+/**
+ * Implementation of the Builder pattern, with a fluent interface that creates a
+ * {@link OAuthService}
+ *
+ * @author Pablo Fernandez
+ *
+ */
+public class ServiceBuilder
+{
+ private String apiKey;
+ private String apiSecret;
+ private String callback;
+ private Api api;
+ private String scope;
+ private SignatureType signatureType;
+ private OutputStream debugStream;
+
+ /**
+ * Default constructor
+ */
+ public ServiceBuilder()
+ {
+ this.callback = OAuthConstants.OUT_OF_BAND;
+ this.signatureType = SignatureType.Header;
+ this.debugStream = null;
+ }
+
+ /**
+ * Configures the {@link Api}
+ *
+ * @param apiClass the class of one of the existent {@link Api}s on org.scribe.api package
+ * @return the {@link ServiceBuilder} instance for method chaining
+ */
+ public ServiceBuilder provider(Class extends Api> apiClass)
+ {
+ this.api = createApi(apiClass);
+ return this;
+ }
+
+ private Api createApi(Class extends Api> apiClass)
+ {
+ Preconditions.checkNotNull(apiClass, "Api class cannot be null");
+ Api api;
+ try
+ {
+ api = apiClass.newInstance();
+ }
+ catch(Exception e)
+ {
+ throw new OAuthException("Error while creating the Api object", e);
+ }
+ return api;
+ }
+
+ /**
+ * Configures the {@link Api}
+ *
+ * Overloaded version. Let's you use an instance instead of a class.
+ *
+ * @param api instance of {@link Api}s
+ * @return the {@link ServiceBuilder} instance for method chaining
+ */
+ public ServiceBuilder provider(Api api)
+ {
+ Preconditions.checkNotNull(api, "Api cannot be null");
+ this.api = api;
+ return this;
+ }
+
+ /**
+ * Adds an OAuth callback url
+ *
+ * @param callback callback url. Must be a valid url or 'oob' for out of band OAuth
+ * @return the {@link ServiceBuilder} instance for method chaining
+ */
+ public ServiceBuilder callback(String callback)
+ {
+ Preconditions.checkNotNull(callback, "Callback can't be null");
+ this.callback = callback;
+ return this;
+ }
+
+ /**
+ * Configures the api key
+ *
+ * @param apiKey The api key for your application
+ * @return the {@link ServiceBuilder} instance for method chaining
+ */
+ public ServiceBuilder apiKey(String apiKey)
+ {
+ Preconditions.checkEmptyString(apiKey, "Invalid Api key");
+ this.apiKey = apiKey;
+ return this;
+ }
+
+ /**
+ * Configures the api secret
+ *
+ * @param apiSecret The api secret for your application
+ * @return the {@link ServiceBuilder} instance for method chaining
+ */
+ public ServiceBuilder apiSecret(String apiSecret)
+ {
+ Preconditions.checkEmptyString(apiSecret, "Invalid Api secret");
+ this.apiSecret = apiSecret;
+ return this;
+ }
+
+ /**
+ * Configures the OAuth scope. This is only necessary in some APIs (like Google's).
+ *
+ * @param scope The OAuth scope
+ * @return the {@link ServiceBuilder} instance for method chaining
+ */
+ public ServiceBuilder scope(String scope)
+ {
+ Preconditions.checkEmptyString(scope, "Invalid OAuth scope");
+ this.scope = scope;
+ return this;
+ }
+
+ /**
+ * Configures the signature type, choose between header, querystring, etc. Defaults to Header
+ *
+ * @param scope The OAuth scope
+ * @return the {@link ServiceBuilder} instance for method chaining
+ */
+ public ServiceBuilder signatureType(SignatureType type)
+ {
+ Preconditions.checkNotNull(type, "Signature type can't be null");
+ this.signatureType = type;
+ return this;
+ }
+
+ public ServiceBuilder debugStream(OutputStream stream)
+ {
+ Preconditions.checkNotNull(stream, "debug stream can't be null");
+ this.debugStream = stream;
+ return this;
+ }
+
+ public ServiceBuilder debug()
+ {
+ this.debugStream(System.out);
+ return this;
+ }
+
+ /**
+ * Returns the fully configured {@link OAuthService}
+ *
+ * @return fully configured {@link OAuthService}
+ */
+ public OAuthService build()
+ {
+ Preconditions.checkNotNull(api, "You must specify a valid api through the provider() method");
+ Preconditions.checkEmptyString(apiKey, "You must provide an api key");
+ Preconditions.checkEmptyString(apiSecret, "You must provide an api secret");
+ return api.createService(new OAuthConfig(apiKey, apiSecret, callback, signatureType, scope, debugStream));
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/AWeberApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/AWeberApi.java
new file mode 100644
index 0000000..53ae1fc
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/AWeberApi.java
@@ -0,0 +1,28 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.Token;
+
+public class AWeberApi extends DefaultApi10a
+{
+ private static final String AUTHORIZE_URL = "https://auth.aweber.com/1.0/oauth/authorize?oauth_token=%s";
+ private static final String REQUEST_TOKEN_ENDPOINT = "https://auth.aweber.com/1.0/oauth/request_token";
+ private static final String ACCESS_TOKEN_ENDPOINT = "https://auth.aweber.com/1.0/oauth/access_token";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return ACCESS_TOKEN_ENDPOINT;
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return REQUEST_TOKEN_ENDPOINT;
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/Api.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/Api.java
new file mode 100644
index 0000000..6664296
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/Api.java
@@ -0,0 +1,25 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+/**
+ * Contains all the configuration needed to instantiate a valid {@link OAuthService}
+ *
+ * @author Pablo Fernandez
+ *
+ */
+public interface Api
+{
+ /**
+ * Creates an {@link OAuthService}
+ *
+ * @param apiKey your application api key
+ * @param apiSecret your application api secret
+ * @param callback the callback url (or 'oob' for out of band OAuth)
+ * @param scope the OAuth scope
+ *
+ * @return fully configured {@link OAuthService}
+ */
+ OAuthService createService(OAuthConfig config);
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/ConstantContactApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/ConstantContactApi.java
new file mode 100644
index 0000000..0588bc4
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/ConstantContactApi.java
@@ -0,0 +1,26 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+public class ConstantContactApi extends DefaultApi10a
+{
+ private static final String AUTHORIZE_URL = "https://oauth.constantcontact.com/ws/oauth/confirm_access?oauth_token=%s";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://oauth.constantcontact.com/ws/oauth/access_token";
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "https://oauth.constantcontact.com/ws/oauth/request_token";
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/ConstantContactApi2.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/ConstantContactApi2.java
new file mode 100644
index 0000000..b5e4cac
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/ConstantContactApi2.java
@@ -0,0 +1,55 @@
+package org.scribe.builder.api;
+
+import java.util.regex.*;
+import org.scribe.exceptions.*;
+import org.scribe.extractors.*;
+import org.scribe.model.*;
+import org.scribe.utils.*;
+
+public class ConstantContactApi2 extends DefaultApi20
+{
+ private static final String AUTHORIZE_URL = "https://oauth2.constantcontact.com/oauth2/oauth/siteowner/authorize?client_id=%s&response_type=code&redirect_uri=%s";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://oauth2.constantcontact.com/oauth2/oauth/token?grant_type=authorization_code";
+ }
+
+ @Override
+ public String getAuthorizationUrl(OAuthConfig config)
+ {
+ return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));
+ }
+
+ @Override
+ public Verb getAccessTokenVerb()
+ {
+ return Verb.POST;
+ }
+
+ @Override
+ public AccessTokenExtractor getAccessTokenExtractor()
+ {
+ return new AccessTokenExtractor()
+ {
+
+ public Token extract(String response)
+ {
+ Preconditions.checkEmptyString(response, "Response body is incorrect. Can't extract a token from an empty string");
+
+ String regex = "\"access_token\"\\s*:\\s*\"([^&\"]+)\"";
+ Matcher matcher = Pattern.compile(regex).matcher(response);
+ if (matcher.find())
+ {
+ String token = OAuthEncoder.decode(matcher.group(1));
+ return new Token(token, "", response);
+ }
+ else
+ {
+ throw new OAuthException("Response body is incorrect. Can't extract a token from this: '" + response + "'", null);
+ }
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/DefaultApi10a.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/DefaultApi10a.java
new file mode 100644
index 0000000..7506986
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/DefaultApi10a.java
@@ -0,0 +1,141 @@
+package org.scribe.builder.api;
+
+import org.scribe.extractors.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+import org.scribe.services.*;
+
+/**
+ * Default implementation of the OAuth protocol, version 1.0a
+ *
+ * This class is meant to be extended by concrete implementations of the API,
+ * providing the endpoints and endpoint-http-verbs.
+ *
+ * If your Api adheres to the 1.0a protocol correctly, you just need to extend
+ * this class and define the getters for your endpoints.
+ *
+ * If your Api does something a bit different, you can override the different
+ * extractors or services, in order to fine-tune the process. Please read the
+ * javadocs of the interfaces to get an idea of what to do.
+ *
+ * @author Pablo Fernandez
+ *
+ */
+public abstract class DefaultApi10a implements Api
+{
+ /**
+ * Returns the access token extractor.
+ *
+ * @return access token extractor
+ */
+ public AccessTokenExtractor getAccessTokenExtractor()
+ {
+ return new TokenExtractorImpl();
+ }
+
+ /**
+ * Returns the base string extractor.
+ *
+ * @return base string extractor
+ */
+ public BaseStringExtractor getBaseStringExtractor()
+ {
+ return new BaseStringExtractorImpl();
+ }
+
+ /**
+ * Returns the header extractor.
+ *
+ * @return header extractor
+ */
+ public HeaderExtractor getHeaderExtractor()
+ {
+ return new HeaderExtractorImpl();
+ }
+
+ /**
+ * Returns the request token extractor.
+ *
+ * @return request token extractor
+ */
+ public RequestTokenExtractor getRequestTokenExtractor()
+ {
+ return new TokenExtractorImpl();
+ }
+
+ /**
+ * Returns the signature service.
+ *
+ * @return signature service
+ */
+ public SignatureService getSignatureService()
+ {
+ return new HMACSha1SignatureService();
+ }
+
+ /**
+ * Returns the timestamp service.
+ *
+ * @return timestamp service
+ */
+ public TimestampService getTimestampService()
+ {
+ return new TimestampServiceImpl();
+ }
+
+ /**
+ * Returns the verb for the access token endpoint (defaults to POST)
+ *
+ * @return access token endpoint verb
+ */
+ public Verb getAccessTokenVerb()
+ {
+ return Verb.POST;
+ }
+
+ /**
+ * Returns the verb for the request token endpoint (defaults to POST)
+ *
+ * @return request token endpoint verb
+ */
+ public Verb getRequestTokenVerb()
+ {
+ return Verb.POST;
+ }
+
+ /**
+ * Returns the URL that receives the request token requests.
+ *
+ * @return request token URL
+ */
+ public abstract String getRequestTokenEndpoint();
+
+ /**
+ * Returns the URL that receives the access token requests.
+ *
+ * @return access token URL
+ */
+ public abstract String getAccessTokenEndpoint();
+
+ /**
+ * Returns the URL where you should redirect your users to authenticate
+ * your application.
+ *
+ * @param requestToken the request token you need to authorize
+ * @return the URL where you should redirect your users
+ */
+ public abstract String getAuthorizationUrl(Token requestToken);
+
+ /**
+ * Returns the {@link OAuthService} for this Api
+ *
+ * @param apiKey Key
+ * @param apiSecret Api Secret
+ * @param callback OAuth callback (either URL or 'oob')
+ * @param scope OAuth scope (optional)
+ */
+ public OAuthService createService(OAuthConfig config)
+ {
+ return new OAuth10aServiceImpl(this, config);
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/DefaultApi20.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/DefaultApi20.java
new file mode 100644
index 0000000..ffb6207
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/DefaultApi20.java
@@ -0,0 +1,70 @@
+package org.scribe.builder.api;
+
+import org.scribe.extractors.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+/**
+ * Default implementation of the OAuth protocol, version 2.0 (draft 11)
+ *
+ * This class is meant to be extended by concrete implementations of the API,
+ * providing the endpoints and endpoint-http-verbs.
+ *
+ * If your Api adheres to the 2.0 (draft 11) protocol correctly, you just need to extend
+ * this class and define the getters for your endpoints.
+ *
+ * If your Api does something a bit different, you can override the different
+ * extractors or services, in order to fine-tune the process. Please read the
+ * javadocs of the interfaces to get an idea of what to do.
+ *
+ * @author Diego Silveira
+ *
+ */
+public abstract class DefaultApi20 implements Api
+{
+
+ /**
+ * Returns the access token extractor.
+ *
+ * @return access token extractor
+ */
+ public AccessTokenExtractor getAccessTokenExtractor()
+ {
+ return new TokenExtractor20Impl();
+ }
+
+ /**
+ * Returns the verb for the access token endpoint (defaults to GET)
+ *
+ * @return access token endpoint verb
+ */
+ public Verb getAccessTokenVerb()
+ {
+ return Verb.GET;
+ }
+
+ /**
+ * Returns the URL that receives the access token requests.
+ *
+ * @return access token URL
+ */
+ public abstract String getAccessTokenEndpoint();
+
+ /**
+ * Returns the URL where you should redirect your users to authenticate
+ * your application.
+ *
+ * @param config OAuth 2.0 configuration param object
+ * @return the URL where you should redirect your users
+ */
+ public abstract String getAuthorizationUrl(OAuthConfig config);
+
+ /**
+ * {@inheritDoc}
+ */
+ public OAuthService createService(OAuthConfig config)
+ {
+ return new OAuth20ServiceImpl(this, config);
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/DiggApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/DiggApi.java
new file mode 100644
index 0000000..b69253e
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/DiggApi.java
@@ -0,0 +1,29 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+public class DiggApi extends DefaultApi10a
+{
+
+ private static final String AUTHORIZATION_URL = "http://digg.com/oauth/authorize?oauth_token=%s";
+ private static final String BASE_URL = "http://services.digg.com/oauth/";
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return BASE_URL + "request_token";
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return BASE_URL + "access_token";
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZATION_URL, requestToken.getToken());
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/DropBoxApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/DropBoxApi.java
new file mode 100644
index 0000000..86f4a71
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/DropBoxApi.java
@@ -0,0 +1,25 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+public class DropBoxApi extends DefaultApi10a
+{
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://api.dropbox.com/1/oauth/access_token";
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return "https://www.dropbox.com/1/oauth/authorize?oauth_token="+requestToken.getToken();
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "https://api.dropbox.com/1/oauth/request_token";
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/EvernoteApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/EvernoteApi.java
new file mode 100644
index 0000000..007f48b
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/EvernoteApi.java
@@ -0,0 +1,49 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.Token;
+
+public class EvernoteApi extends DefaultApi10a
+{
+ private static final String AUTHORIZATION_URL = "https://www.evernote.com/OAuth.action?oauth_token=%s";
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "https://www.evernote.com/oauth";
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://www.evernote.com/oauth";
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZATION_URL, requestToken.getToken());
+ }
+
+ public static class Sandbox extends EvernoteApi
+ {
+ private static final String SANDBOX_URL = "https://sandbox.evernote.com";
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return SANDBOX_URL + "/oauth";
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return SANDBOX_URL + "/oauth";
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(SANDBOX_URL + "/OAuth.action?oauth_token=%s", requestToken.getToken());
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/FacebookApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/FacebookApi.java
new file mode 100644
index 0000000..996a651
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/FacebookApi.java
@@ -0,0 +1,33 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+import org.scribe.utils.*;
+
+public class FacebookApi extends DefaultApi20
+{
+ private static final String AUTHORIZE_URL = "https://www.facebook.com/dialog/oauth?client_id=%s&redirect_uri=%s";
+ private static final String SCOPED_AUTHORIZE_URL = AUTHORIZE_URL + "&scope=%s";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://graph.facebook.com/oauth/access_token";
+ }
+
+ @Override
+ public String getAuthorizationUrl(OAuthConfig config)
+ {
+ Preconditions.checkValidUrl(config.getCallback(), "Must provide a valid url as callback. Facebook does not support OOB");
+
+ // Append scope if present
+ if(config.hasScope())
+ {
+ return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()), OAuthEncoder.encode(config.getScope()));
+ }
+ else
+ {
+ return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/FlickrApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/FlickrApi.java
new file mode 100644
index 0000000..a630436
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/FlickrApi.java
@@ -0,0 +1,40 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+/**
+ * OAuth API for Flickr.
+ *
+ * @author Darren Greaves
+ * @see Flickr API
+ */
+public class FlickrApi extends DefaultApi10a
+{
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "http://www.flickr.com/services/oauth/access_token";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return "http://www.flickr.com/services/oauth/authorize?oauth_token=" + requestToken.getToken();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "http://www.flickr.com/services/oauth/request_token";
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/Foursquare2Api.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/Foursquare2Api.java
new file mode 100644
index 0000000..d11def9
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/Foursquare2Api.java
@@ -0,0 +1,29 @@
+package org.scribe.builder.api;
+
+import org.scribe.extractors.*;
+import org.scribe.model.*;
+import org.scribe.utils.*;
+
+public class Foursquare2Api extends DefaultApi20
+{
+ private static final String AUTHORIZATION_URL = "https://foursquare.com/oauth2/authenticate?client_id=%s&response_type=code&redirect_uri=%s";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://foursquare.com/oauth2/access_token?grant_type=authorization_code";
+ }
+
+ @Override
+ public String getAuthorizationUrl(OAuthConfig config)
+ {
+ Preconditions.checkValidUrl(config.getCallback(), "Must provide a valid url as callback. Foursquare2 does not support OOB");
+ return String.format(AUTHORIZATION_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));
+ }
+
+ @Override
+ public AccessTokenExtractor getAccessTokenExtractor()
+ {
+ return new JsonTokenExtractor();
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/FoursquareApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/FoursquareApi.java
new file mode 100644
index 0000000..060a76b
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/FoursquareApi.java
@@ -0,0 +1,26 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.Token;
+
+public class FoursquareApi extends DefaultApi10a
+{
+ private static final String AUTHORIZATION_URL = "http://foursquare.com/oauth/authorize?oauth_token=%s";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "http://foursquare.com/oauth/access_token";
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "http://foursquare.com/oauth/request_token";
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZATION_URL, requestToken.getToken());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/FreelancerApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/FreelancerApi.java
new file mode 100644
index 0000000..482e66f
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/FreelancerApi.java
@@ -0,0 +1,61 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+public class FreelancerApi extends DefaultApi10a
+{
+ private static final String AUTHORIZATION_URL = "http://www.freelancer.com/users/api-token/auth.php?oauth_token=%s";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "http://api.freelancer.com/RequestAccessToken/requestAccessToken.xml?";
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "http://api.freelancer.com/RequestRequestToken/requestRequestToken.xml";
+ }
+
+ @Override
+ public Verb getAccessTokenVerb()
+ {
+ return Verb.GET;
+ }
+
+ @Override
+ public Verb getRequestTokenVerb()
+ {
+ return Verb.GET;
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZATION_URL, requestToken.getToken());
+ }
+
+ public static class Sandbox extends FreelancerApi
+ {
+ private static final String SANDBOX_AUTHORIZATION_URL = "http://www.sandbox.freelancer.com/users/api-token/auth.php";
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "http://api.sandbox.freelancer.com/RequestRequestToken/requestRequestToken.xml";
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "http://api.sandbox.freelancer.com/RequestAccessToken/requestAccessToken.xml?";
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(SANDBOX_AUTHORIZATION_URL + "?oauth_token=%s", requestToken.getToken());
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/GetGlueApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/GetGlueApi.java
new file mode 100644
index 0000000..3a7560f
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/GetGlueApi.java
@@ -0,0 +1,29 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.Token;
+
+public class GetGlueApi extends DefaultApi10a
+{
+ private static final String AUTHORIZE_URL = "http://getglue.com/oauth/authorize?oauth_token=%s";
+ private static final String REQUEST_TOKEN_RESOURCE = "https://api.getglue.com/oauth/request_token";
+ private static final String ACCESS_TOKEN_RESOURCE = "https://api.getglue.com/oauth/access_token";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return ACCESS_TOKEN_RESOURCE;
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return REQUEST_TOKEN_RESOURCE;
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/GoogleApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/GoogleApi.java
new file mode 100644
index 0000000..9c86e5e
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/GoogleApi.java
@@ -0,0 +1,38 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+public class GoogleApi extends DefaultApi10a
+{
+ private static final String AUTHORIZATION_URL = "https://www.google.com/accounts/OAuthAuthorizeToken?oauth_token=%s";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://www.google.com/accounts/OAuthGetAccessToken";
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "https://www.google.com/accounts/OAuthGetRequestToken";
+ }
+
+ @Override
+ public Verb getAccessTokenVerb()
+ {
+ return Verb.GET;
+ }
+
+ @Override
+ public Verb getRequestTokenVerb()
+ {
+ return Verb.GET;
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZATION_URL, requestToken.getToken());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/ImgUrApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/ImgUrApi.java
new file mode 100644
index 0000000..06dd691
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/ImgUrApi.java
@@ -0,0 +1,32 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+/**
+ * OAuth API for ImgUr
+ *
+ * @author David Wursteisen
+ * @see ImgUr API
+ */
+public class ImgUrApi extends DefaultApi10a
+{
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "https://api.imgur.com/oauth/request_token";
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://api.imgur.com/oauth/access_token";
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format("https://api.imgur.com/oauth/authorize?oauth_token=%s", requestToken.getToken());
+ }
+}
+
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/KaixinApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/KaixinApi.java
new file mode 100644
index 0000000..5b0e0d5
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/KaixinApi.java
@@ -0,0 +1,40 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+public class KaixinApi extends DefaultApi10a
+{
+ private static final String REQUEST_TOKEN_URL = "http://api.kaixin001.com/oauth/request_token";
+ private static final String ACCESS_TOKEN_URL = "http://api.kaixin001.com/oauth/access_token";
+ private static final String AUTHORIZE_URL = "http://api.kaixin001.com/oauth/authorize?oauth_token=%s";
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return REQUEST_TOKEN_URL;
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return ACCESS_TOKEN_URL;
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+
+ @Override
+ public Verb getRequestTokenVerb()
+ {
+ return Verb.GET;
+ }
+
+ @Override
+ public Verb getAccessTokenVerb()
+ {
+ return Verb.GET;
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/KaixinApi20.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/KaixinApi20.java
new file mode 100644
index 0000000..9e27bcb
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/KaixinApi20.java
@@ -0,0 +1,41 @@
+package org.scribe.builder.api;
+
+import org.scribe.extractors.*;
+import org.scribe.model.*;
+import org.scribe.utils.*;
+
+/**
+ * Kaixin(http://www.kaixin001.com/) open platform api based on OAuth 2.0.
+ */
+public class KaixinApi20 extends DefaultApi20
+{
+
+ private static final String AUTHORIZE_URL = "http://api.kaixin001.com/oauth2/authorize?client_id=%s&redirect_uri=%s&response_type=code";
+ private static final String SCOPED_AUTHORIZE_URL = AUTHORIZE_URL + "&scope=%s";
+
+ @Override
+ public AccessTokenExtractor getAccessTokenExtractor()
+ {
+ return new JsonTokenExtractor();
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://api.kaixin001.com/oauth2/access_token?grant_type=authorization_code";
+ }
+
+ @Override
+ public String getAuthorizationUrl(OAuthConfig config)
+ {
+ // Append scope if present
+ if (config.hasScope())
+ {
+ return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()), OAuthEncoder.encode(config.getScope()));
+ }
+ else
+ {
+ return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/LinkedInApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/LinkedInApi.java
new file mode 100644
index 0000000..ee6becd
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/LinkedInApi.java
@@ -0,0 +1,57 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+import java.util.*;
+
+public class LinkedInApi extends DefaultApi10a
+{
+ private static final String AUTHORIZE_URL = "https://api.linkedin.com/uas/oauth/authenticate?oauth_token=%s";
+ private static final String REQUEST_TOKEN_URL = "https://api.linkedin.com/uas/oauth/requestToken";
+
+ private final Set scopes;
+
+ public LinkedInApi()
+ {
+ scopes = Collections.emptySet();
+ }
+
+ public LinkedInApi(Set scopes)
+ {
+ this.scopes = Collections.unmodifiableSet(scopes);
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://api.linkedin.com/uas/oauth/accessToken";
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return scopes.isEmpty() ? REQUEST_TOKEN_URL : REQUEST_TOKEN_URL + "?scope=" + scopesAsString();
+ }
+
+ private String scopesAsString()
+ {
+ StringBuilder builder = new StringBuilder();
+ for(String scope : scopes)
+ {
+ builder.append("+" + scope);
+ }
+ return builder.substring(1);
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+
+ public static LinkedInApi withScopes(String... scopes)
+ {
+ Set scopeSet = new HashSet(Arrays.asList(scopes));
+ return new LinkedInApi(scopeSet);
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/LiveApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/LiveApi.java
new file mode 100644
index 0000000..18140f6
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/LiveApi.java
@@ -0,0 +1,40 @@
+package org.scribe.builder.api;
+
+import org.scribe.extractors.*;
+import org.scribe.model.*;
+import org.scribe.utils.*;
+
+public class LiveApi extends DefaultApi20
+{
+
+ private static final String AUTHORIZE_URL = "https://oauth.live.com/authorize?client_id=%s&redirect_uri=%s&response_type=code";
+ private static final String SCOPED_AUTHORIZE_URL = AUTHORIZE_URL + "&scope=%s";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://oauth.live.com/token?grant_type=authorization_code";
+ }
+
+ @Override
+ public String getAuthorizationUrl(OAuthConfig config)
+ {
+ Preconditions.checkValidUrl(config.getCallback(), "Must provide a valid url as callback. Live does not support OOB");
+
+ // Append scope if present
+ if (config.hasScope())
+ {
+ return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()), OAuthEncoder.encode(config.getScope()));
+ }
+ else
+ {
+ return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));
+ }
+ }
+
+ @Override
+ public AccessTokenExtractor getAccessTokenExtractor()
+ {
+ return new JsonTokenExtractor();
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/LoveFilmApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/LoveFilmApi.java
new file mode 100644
index 0000000..81a5bb8
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/LoveFilmApi.java
@@ -0,0 +1,28 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.Token;
+
+public class LoveFilmApi extends DefaultApi10a
+{
+ private static final String REQUEST_TOKEN_URL = "http://openapi.lovefilm.com/oauth/request_token";
+ private static final String ACCESS_TOKEN_URL = "http://openapi.lovefilm.com/oauth/access_token";
+ private static final String AUTHORIZE_URL = "https://www.lovefilm.com/activate?oauth_token=%s";
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return REQUEST_TOKEN_URL;
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return ACCESS_TOKEN_URL;
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/MeetupApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/MeetupApi.java
new file mode 100644
index 0000000..8f63e39
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/MeetupApi.java
@@ -0,0 +1,30 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.Token;
+
+/**
+ * OAuth access to the Meetup.com API.
+ * For more information visit http://www.meetup.com/api
+ */
+public class MeetupApi extends DefaultApi10a
+{
+ private static final String AUTHORIZE_URL = "http://www.meetup.com/authenticate?oauth_token=%s";
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "http://api.meetup.com/oauth/request/";
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "http://api.meetup.com/oauth/access/";
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/MendeleyApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/MendeleyApi.java
new file mode 100644
index 0000000..c6e0ece
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/MendeleyApi.java
@@ -0,0 +1,43 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+/**
+ * @author Arieh "Vainolo" Bibliowicz
+ * @see http://apidocs.mendeley.com/home/authentication
+ */
+public class MendeleyApi extends DefaultApi10a
+{
+
+ private static final String AUTHORIZATION_URL = "http://api.mendeley.com/oauth/authorize?oauth_token=%s";
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "http://api.mendeley.com/oauth/request_token/";
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "http://api.mendeley.com/oauth/access_token/";
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZATION_URL, requestToken.getToken());
+ }
+
+ @Override
+ public Verb getAccessTokenVerb()
+ {
+ return Verb.GET;
+ }
+
+ @Override
+ public Verb getRequestTokenVerb()
+ {
+ return Verb.GET;
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/MisoApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/MisoApi.java
new file mode 100644
index 0000000..a6d88d3
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/MisoApi.java
@@ -0,0 +1,29 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.Token;
+
+public class MisoApi extends DefaultApi10a
+{
+ private static final String AUTHORIZE_URL = "http://gomiso.com/oauth/authorize?oauth_token=%s";
+ private static final String REQUEST_TOKEN_RESOURCE = "http://gomiso.com/oauth/request_token";
+ private static final String ACCESS_TOKEN_RESOURCE = "http://gomiso.com/oauth/access_token";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return ACCESS_TOKEN_RESOURCE;
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return REQUEST_TOKEN_RESOURCE;
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/NetProspexApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/NetProspexApi.java
new file mode 100644
index 0000000..8257de7
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/NetProspexApi.java
@@ -0,0 +1,28 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.Token;
+
+public class NetProspexApi extends DefaultApi10a
+{
+ private static final String REQUEST_TOKEN_URL = "https://api.netprospex.com/1.0/oauth/request-token";
+ private static final String ACCESS_TOKEN_URL = "https://api.netprospex.com/1.0/oauth/access-token";
+ private static final String AUTHORIZE_URL = "https://api.netprospex.com/1.0/oauth/authorize?oauth_token=%s";
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return REQUEST_TOKEN_URL;
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return ACCESS_TOKEN_URL;
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/NeteaseWeibooApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/NeteaseWeibooApi.java
new file mode 100644
index 0000000..fae38ac
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/NeteaseWeibooApi.java
@@ -0,0 +1,47 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+public class NeteaseWeibooApi extends DefaultApi10a
+{
+ private static final String REQUEST_TOKEN_URL = "http://api.t.163.com/oauth/request_token";
+ private static final String ACCESS_TOKEN_URL = "http://api.t.163.com/oauth/access_token";
+ private static final String AUTHORIZE_URL = "http://api.t.163.com/oauth/authorize?oauth_token=%s";
+ private static final String AUTHENTICATE_URL = "http://api.t.163.com/oauth/authenticate?oauth_token=%s";
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return REQUEST_TOKEN_URL;
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return ACCESS_TOKEN_URL;
+ }
+
+ @Override
+ /**
+ * this method will ignore your callback
+ * if you're creating a desktop client please choose this url
+ * else your can call getAuthenticateUrl
+ *
+ * via http://open.t.163.com/wiki/index.php?title=%E8%AF%B7%E6%B1%82%E7%94%A8%E6%88%B7%E6%8E%88%E6%9D%83Token(oauth/authorize)
+ */
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+
+ /**
+ * this method is for web client with callback url
+ * if you're creating a desktop client please call getAuthorizationUrl
+ *
+ * via http://open.t.163.com/wiki/index.php?title=%E8%AF%B7%E6%B1%82%E7%94%A8%E6%88%B7%E6%8E%88%E6%9D%83Token(oauth/authenticate)
+ */
+ public String getAuthenticateUrl(Token requestToken)
+ {
+ return String.format(AUTHENTICATE_URL, requestToken.getToken());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/PlurkApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/PlurkApi.java
new file mode 100644
index 0000000..22b1ddb
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/PlurkApi.java
@@ -0,0 +1,39 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.Token;
+
+public class PlurkApi extends DefaultApi10a
+{
+ private static final String REQUEST_TOKEN_URL = "http://www.plurk.com/OAuth/request_token";
+ private static final String AUTHORIZATION_URL = "http://www.plurk.com/OAuth/authorize?oauth_token=%s";
+ private static final String ACCESS_TOKEN_URL = "http://www.plurk.com/OAuth/access_token";
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return REQUEST_TOKEN_URL;
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZATION_URL, requestToken.getToken());
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return ACCESS_TOKEN_URL;
+ }
+
+ public static class Mobile extends PlurkApi
+ {
+ private static final String AUTHORIZATION_URL = "http://www.plurk.com/m/authorize?oauth_token=%s";
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZATION_URL, requestToken.getToken());
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/Px500Api.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/Px500Api.java
new file mode 100644
index 0000000..f7f3b0e
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/Px500Api.java
@@ -0,0 +1,26 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+public class Px500Api extends DefaultApi10a
+{
+ private static final String AUTHORIZATION_URL = "https://api.500px.com/v1/oauth/authorize?oauth_token=%s";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://api.500px.com/v1/oauth/access_token";
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "https://api.500px.com/v1/oauth/request_token";
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZATION_URL, requestToken.getToken());
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/QWeiboApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/QWeiboApi.java
new file mode 100644
index 0000000..e16f288
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/QWeiboApi.java
@@ -0,0 +1,28 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+public class QWeiboApi extends DefaultApi10a
+{
+ private static final String REQUEST_TOKEN_URL = "https://open.t.qq.com/cgi-bin/request_token";
+ private static final String ACCESS_TOKEN_URL = "https://open.t.qq.com/cgi-bin/access_token";
+ private static final String AUTHORIZE_URL = "https://open.t.qq.com/cgi-bin/authorize?oauth_token=%s";
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return REQUEST_TOKEN_URL;
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return ACCESS_TOKEN_URL;
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/RenrenApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/RenrenApi.java
new file mode 100644
index 0000000..b31337b
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/RenrenApi.java
@@ -0,0 +1,40 @@
+package org.scribe.builder.api;
+
+import org.scribe.extractors.*;
+import org.scribe.model.*;
+import org.scribe.utils.*;
+
+/**
+ * Renren(http://www.renren.com/) OAuth 2.0 based api.
+ */
+public class RenrenApi extends DefaultApi20
+{
+ private static final String AUTHORIZE_URL = "https://graph.renren.com/oauth/authorize?client_id=%s&redirect_uri=%s&response_type=code";
+ private static final String SCOPED_AUTHORIZE_URL = AUTHORIZE_URL + "&scope=%s";
+
+ @Override
+ public AccessTokenExtractor getAccessTokenExtractor()
+ {
+ return new JsonTokenExtractor();
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://graph.renren.com/oauth/token?grant_type=authorization_code";
+ }
+
+ @Override
+ public String getAuthorizationUrl(OAuthConfig config)
+ {
+ // Append scope if present
+ if (config.hasScope())
+ {
+ return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()), OAuthEncoder.encode(config.getScope()));
+ }
+ else
+ {
+ return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SapoApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SapoApi.java
new file mode 100644
index 0000000..9771daf
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SapoApi.java
@@ -0,0 +1,40 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+public class SapoApi extends DefaultApi10a
+{
+ private static final String AUTHORIZE_URL = "https://id.sapo.pt/oauth/authorize?oauth_token=%s";
+ private static final String ACCESS_URL = "https://id.sapo.pt/oauth/access_token";
+ private static final String REQUEST_URL = "https://id.sapo.pt/oauth/request_token";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return ACCESS_URL;
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return REQUEST_URL;
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+
+ @Override
+ public Verb getRequestTokenVerb()
+ {
+ return Verb.GET;
+ }
+
+ @Override
+ public Verb getAccessTokenVerb()
+ {
+ return Verb.GET;
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SimpleGeoApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SimpleGeoApi.java
new file mode 100644
index 0000000..3e19df7
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SimpleGeoApi.java
@@ -0,0 +1,29 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.Token;
+
+/**
+ * @author: Pablo Fernandez
+ */
+public class SimpleGeoApi extends DefaultApi10a
+{
+ private static final String ENDPOINT = "these are not used since SimpleGeo uses 2 legged OAuth";
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return ENDPOINT;
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return ENDPOINT;
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return ENDPOINT;
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SinaWeiboApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SinaWeiboApi.java
new file mode 100644
index 0000000..14951d3
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SinaWeiboApi.java
@@ -0,0 +1,28 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+public class SinaWeiboApi extends DefaultApi10a
+{
+ private static final String REQUEST_TOKEN_URL = "http://api.t.sina.com.cn/oauth/request_token";
+ private static final String ACCESS_TOKEN_URL = "http://api.t.sina.com.cn/oauth/access_token";
+ private static final String AUTHORIZE_URL = "http://api.t.sina.com.cn/oauth/authorize?oauth_token=%s";
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return REQUEST_TOKEN_URL;
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return ACCESS_TOKEN_URL;
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SinaWeiboApi20.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SinaWeiboApi20.java
new file mode 100644
index 0000000..e0744c4
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SinaWeiboApi20.java
@@ -0,0 +1,46 @@
+package org.scribe.builder.api;
+
+import org.scribe.extractors.*;
+import org.scribe.model.*;
+import org.scribe.utils.*;
+
+/**
+ * SinaWeibo OAuth 2.0 api.
+ */
+public class SinaWeiboApi20 extends DefaultApi20
+{
+ private static final String AUTHORIZE_URL = "https://api.weibo.com/oauth2/authorize?client_id=%s&redirect_uri=%s&response_type=code";
+ private static final String SCOPED_AUTHORIZE_URL = AUTHORIZE_URL + "&scope=%s";
+
+ @Override
+ public Verb getAccessTokenVerb()
+ {
+ return Verb.POST;
+ }
+
+ @Override
+ public AccessTokenExtractor getAccessTokenExtractor()
+ {
+ return new JsonTokenExtractor();
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://api.weibo.com/oauth2/access_token?grant_type=authorization_code";
+ }
+
+ @Override
+ public String getAuthorizationUrl(OAuthConfig config)
+ {
+ // Append scope if present
+ if (config.hasScope())
+ {
+ return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()), OAuthEncoder.encode(config.getScope()));
+ }
+ else
+ {
+ return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SkyrockApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SkyrockApi.java
new file mode 100644
index 0000000..b0e76a3
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SkyrockApi.java
@@ -0,0 +1,35 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+/**
+ * OAuth API for Skyrock.
+ *
+ * @author Nicolas Quiénot
+ * @see Skyrock.com API
+ */
+public class SkyrockApi extends DefaultApi10a
+{
+ private static final String API_ENDPOINT = "https://api.skyrock.com/v2";
+ private static final String REQUEST_TOKEN_RESOURCE = "/oauth/initiate";
+ private static final String AUTHORIZE_URL = "/oauth/authorize?oauth_token=%s";
+ private static final String ACCESS_TOKEN_RESOURCE = "/oauth/token";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return API_ENDPOINT + ACCESS_TOKEN_RESOURCE;
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return API_ENDPOINT + REQUEST_TOKEN_RESOURCE;
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(API_ENDPOINT + AUTHORIZE_URL, requestToken.getToken());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SohuWeiboApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SohuWeiboApi.java
new file mode 100644
index 0000000..1f927b7
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/SohuWeiboApi.java
@@ -0,0 +1,28 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+public class SohuWeiboApi extends DefaultApi10a
+{
+ private static final String REQUEST_TOKEN_URL = "http://api.t.sohu.com/oauth/request_token";
+ private static final String ACCESS_TOKEN_URL = "http://api.t.sohu.com/oauth/access_token";
+ private static final String AUTHORIZE_URL = "http://api.t.sohu.com/oauth/authorize?oauth_token=%s";
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return REQUEST_TOKEN_URL;
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return ACCESS_TOKEN_URL;
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/TrelloApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/TrelloApi.java
new file mode 100644
index 0000000..9e46730
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/TrelloApi.java
@@ -0,0 +1,27 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+public class TrelloApi extends DefaultApi10a
+{
+ private static final String AUTHORIZE_URL = "https://trello.com/1/OAuthAuthorizeToken?oauth_token=%s";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://trello.com/1/OAuthGetAccessToken";
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "https://trello.com/1/OAuthGetRequestToken";
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/TumblrApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/TumblrApi.java
new file mode 100644
index 0000000..ee680ee
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/TumblrApi.java
@@ -0,0 +1,28 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.Token;
+
+public class TumblrApi extends DefaultApi10a
+{
+ private static final String AUTHORIZE_URL = "https://www.tumblr.com/oauth/authorize?oauth_token=%s";
+ private static final String REQUEST_TOKEN_RESOURCE = "http://www.tumblr.com/oauth/request_token";
+ private static final String ACCESS_TOKEN_RESOURCE = "http://www.tumblr.com/oauth/access_token";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return ACCESS_TOKEN_RESOURCE;
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return REQUEST_TOKEN_RESOURCE;
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/TwitterApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/TwitterApi.java
new file mode 100644
index 0000000..86494c5
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/TwitterApi.java
@@ -0,0 +1,42 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.Token;
+
+public class TwitterApi extends DefaultApi10a
+{
+ private static final String AUTHORIZE_URL = "https://api.twitter.com/oauth/authorize?oauth_token=%s";
+ private static final String REQUEST_TOKEN_RESOURCE = "api.twitter.com/oauth/request_token";
+ private static final String ACCESS_TOKEN_RESOURCE = "api.twitter.com/oauth/access_token";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://" + ACCESS_TOKEN_RESOURCE;
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "https://" + REQUEST_TOKEN_RESOURCE;
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+
+ /**
+ * Twitter 'friendlier' authorization endpoint for OAuth.
+ */
+ public static class Authenticate extends TwitterApi
+ {
+ private static final String AUTHENTICATE_URL = "https://api.twitter.com/oauth/authenticate?oauth_token=%s";
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHENTICATE_URL, requestToken.getToken());
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/UbuntuOneApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/UbuntuOneApi.java
new file mode 100644
index 0000000..2a72c3a
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/UbuntuOneApi.java
@@ -0,0 +1,40 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.Token;
+import org.scribe.services.*;
+
+/**
+ * @author Julio Gutierrez
+ *
+ * Sep 6, 2012
+ */
+public class UbuntuOneApi extends DefaultApi10a
+{
+
+ private static final String AUTHORIZATION_URL = "https://one.ubuntu.com/oauth/authorize/?oauth_token=%s";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://one.ubuntu.com/oauth/access/";
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZATION_URL, requestToken.getToken());
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "https://one.ubuntu.com/oauth/request/";
+ }
+
+ @Override
+ public SignatureService getSignatureService()
+ {
+ return new PlaintextSignatureService();
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/ViadeoApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/ViadeoApi.java
new file mode 100644
index 0000000..0f5e77e
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/ViadeoApi.java
@@ -0,0 +1,42 @@
+package org.scribe.builder.api;
+
+import org.scribe.extractors.AccessTokenExtractor;
+import org.scribe.model.OAuthConfig;
+import org.scribe.utils.OAuthEncoder;
+import org.scribe.utils.Preconditions;
+
+import org.scribe.extractors.JsonTokenExtractor;
+
+public class ViadeoApi extends DefaultApi20
+{
+ private static final String AUTHORIZE_URL = "https://secure.viadeo.com/oauth-provider/authorize2?client_id=%s&redirect_uri=%s&response_type=code";
+ private static final String SCOPED_AUTHORIZE_URL = AUTHORIZE_URL + "&scope=%s";
+
+ @Override
+ public AccessTokenExtractor getAccessTokenExtractor()
+ {
+ return new JsonTokenExtractor();
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://secure.viadeo.com/oauth-provider/access_token2?grant_type=authorization_code";
+ }
+
+ @Override
+ public String getAuthorizationUrl(OAuthConfig config)
+ {
+ Preconditions.checkValidUrl(config.getCallback(), "Must provide a valid url as callback. Viadeo does not support OOB");
+
+ // Append scope if present
+ if(config.hasScope())
+ {
+ return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()), OAuthEncoder.encode(config.getScope()));
+ }
+ else
+ {
+ return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/VimeoApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/VimeoApi.java
new file mode 100644
index 0000000..231895d
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/VimeoApi.java
@@ -0,0 +1,26 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.Token;
+
+public class VimeoApi extends DefaultApi10a
+{
+ private static final String AUTHORIZATION_URL = "http://vimeo.com/oauth/authorize?oauth_token=%s";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "http://vimeo.com/oauth/access_token";
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "http://vimeo.com/oauth/request_token";
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZATION_URL, requestToken.getToken());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/VkontakteApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/VkontakteApi.java
new file mode 100644
index 0000000..e12f395
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/VkontakteApi.java
@@ -0,0 +1,41 @@
+package org.scribe.builder.api;
+
+import org.scribe.extractors.*;
+import org.scribe.utils.*;
+import org.scribe.model.*;
+
+/**
+ * @author Boris G. Tsirkin
+ * @since 20.4.2011
+ */
+public class VkontakteApi extends DefaultApi20
+{
+ private static final String AUTHORIZE_URL = "https://oauth.vk.com/authorize?client_id=%s&redirect_uri=%s&response_type=code";
+ private static final String SCOPED_AUTHORIZE_URL = String.format("%s&scope=%%s", AUTHORIZE_URL);
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://api.vkontakte.ru/oauth/access_token";
+ }
+
+ @Override
+ public String getAuthorizationUrl(OAuthConfig config)
+ {
+ Preconditions.checkValidUrl(config.getCallback(), "Valid url is required for a callback. Vkontakte does not support OOB");
+ if(config.hasScope())// Appending scope if present
+ {
+ return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()), OAuthEncoder.encode(config.getScope()));
+ }
+ else
+ {
+ return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));
+ }
+ }
+
+ @Override
+ public AccessTokenExtractor getAccessTokenExtractor()
+ {
+ return new JsonTokenExtractor();
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/XingApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/XingApi.java
new file mode 100755
index 0000000..ec8823e
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/XingApi.java
@@ -0,0 +1,27 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+
+public class XingApi extends DefaultApi10a
+{
+ private static final String AUTHORIZE_URL = "https://api.xing.com/v1/authorize?oauth_token=%s";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://api.xing.com/v1/access_token";
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "https://api.xing.com/v1/request_token";
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/YahooApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/YahooApi.java
new file mode 100644
index 0000000..e8a29a7
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/YahooApi.java
@@ -0,0 +1,26 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.Token;
+
+public class YahooApi extends DefaultApi10a
+{
+ private static final String AUTHORIZE_URL = "https://api.login.yahoo.com/oauth/v2/request_auth?oauth_token=%s";
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://api.login.yahoo.com/oauth/v2/get_token";
+ }
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "https://api.login.yahoo.com/oauth/v2/get_request_token";
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZE_URL, requestToken.getToken());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/YammerApi.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/YammerApi.java
new file mode 100644
index 0000000..e06543d
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/builder/api/YammerApi.java
@@ -0,0 +1,33 @@
+package org.scribe.builder.api;
+
+import org.scribe.model.*;
+import org.scribe.services.*;
+
+public class YammerApi extends DefaultApi10a
+{
+ private static final String AUTHORIZATION_URL = "https://www.yammer.com/oauth/authorize?oauth_token=%s";
+
+ @Override
+ public String getRequestTokenEndpoint()
+ {
+ return "https://www.yammer.com/oauth/request_token";
+ }
+
+ @Override
+ public String getAccessTokenEndpoint()
+ {
+ return "https://www.yammer.com/oauth/access_token";
+ }
+
+ @Override
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return String.format(AUTHORIZATION_URL, requestToken.getToken());
+ }
+
+ @Override
+ public SignatureService getSignatureService()
+ {
+ return new PlaintextSignatureService();
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/exceptions/OAuthConnectionException.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/exceptions/OAuthConnectionException.java
new file mode 100644
index 0000000..918de81
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/exceptions/OAuthConnectionException.java
@@ -0,0 +1,14 @@
+package org.scribe.exceptions;
+
+/**
+ * @author: Pablo Fernandez
+ */
+public class OAuthConnectionException extends OAuthException
+{
+ private static final String MSG = "There was a problem while creating a connection to the remote service.";
+
+ public OAuthConnectionException(Exception e)
+ {
+ super(MSG, e);
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/exceptions/OAuthException.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/exceptions/OAuthException.java
new file mode 100644
index 0000000..85f49d9
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/exceptions/OAuthException.java
@@ -0,0 +1,33 @@
+package org.scribe.exceptions;
+
+/**
+ * Default scribe exception.
+ * Represents a problem in the OAuth signing process
+ *
+ * @author Pablo Fernandez
+ */
+public class OAuthException extends RuntimeException
+{
+
+ /**
+ * Default constructor
+ * @param message message explaining what went wrong
+ * @param e original exception
+ */
+ public OAuthException(String message, Exception e)
+ {
+ super(message, e);
+ }
+
+ /**
+ * No-exception constructor. Used when there is no original exception
+ *
+ * @param message message explaining what went wrong
+ */
+ public OAuthException(String message)
+ {
+ super(message, null);
+ }
+
+ private static final long serialVersionUID = 1L;
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/exceptions/OAuthParametersMissingException.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/exceptions/OAuthParametersMissingException.java
new file mode 100644
index 0000000..8407ce4
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/exceptions/OAuthParametersMissingException.java
@@ -0,0 +1,26 @@
+package org.scribe.exceptions;
+
+import org.scribe.model.*;
+
+/**
+ * Specialized exception that represents a missing OAuth parameter.
+ *
+ * @author Pablo Fernandez
+ */
+public class OAuthParametersMissingException extends OAuthException
+{
+
+ private static final long serialVersionUID = 1745308760111976671L;
+ private static final String MSG = "Could not find oauth parameters in request: %s. "
+ + "OAuth parameters must be specified with the addOAuthParameter() method";
+
+ /**
+ * Default constructor.
+ *
+ * @param request OAuthRequest that caused the error
+ */
+ public OAuthParametersMissingException(OAuthRequest request)
+ {
+ super(String.format(MSG, request));
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/exceptions/OAuthSignatureException.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/exceptions/OAuthSignatureException.java
new file mode 100644
index 0000000..94692be
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/exceptions/OAuthSignatureException.java
@@ -0,0 +1,24 @@
+package org.scribe.exceptions;
+
+/**
+ * Specialized exception that represents a problem in the signature
+ *
+ * @author Pablo Fernandez
+ */
+public class OAuthSignatureException extends OAuthException
+{
+ private static final long serialVersionUID = 1L;
+ private static final String MSG = "Error while signing string: %s";
+
+ /**
+ * Default constructor
+ *
+ * @param stringToSign plain string that gets signed (HMAC-SHA, etc)
+ * @param e original exception
+ */
+ public OAuthSignatureException(String stringToSign, Exception e)
+ {
+ super(String.format(MSG, stringToSign), e);
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/AccessTokenExtractor.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/AccessTokenExtractor.java
new file mode 100644
index 0000000..3c0dd34
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/AccessTokenExtractor.java
@@ -0,0 +1,19 @@
+package org.scribe.extractors;
+
+import org.scribe.model.*;
+
+/**
+ * Simple command object that extracts a {@link Token} from a String
+ *
+ * @author Pablo Fernandez
+ */
+public interface AccessTokenExtractor
+{
+ /**
+ * Extracts the access token from the contents of an Http Response
+ *
+ * @param response the contents of the response
+ * @return OAuth access token
+ */
+ public Token extract(String response);
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/BaseStringExtractor.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/BaseStringExtractor.java
new file mode 100644
index 0000000..83ddd10
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/BaseStringExtractor.java
@@ -0,0 +1,21 @@
+package org.scribe.extractors;
+
+import org.scribe.model.*;
+
+/**
+ * Simple command object that extracts a base string from a {@link OAuthRequest}
+ *
+ * @author Pablo Fernandez
+ */
+public interface BaseStringExtractor
+{
+ /**
+ * Extracts an url-encoded base string from the {@link OAuthRequest}.
+ *
+ * See the oauth spec for more info on this.
+ *
+ * @param request the OAuthRequest
+ * @return the url-encoded base string
+ */
+ String extract(OAuthRequest request);
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/BaseStringExtractorImpl.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/BaseStringExtractorImpl.java
new file mode 100644
index 0000000..ca21a0d
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/BaseStringExtractorImpl.java
@@ -0,0 +1,48 @@
+package org.scribe.extractors;
+
+import org.scribe.exceptions.*;
+import org.scribe.model.*;
+import org.scribe.utils.*;
+
+/**
+ * Default implementation of {@link BaseStringExtractor}. Conforms to OAuth 1.0a
+ *
+ * @author Pablo Fernandez
+ *
+ */
+public class BaseStringExtractorImpl implements BaseStringExtractor
+{
+
+ private static final String AMPERSAND_SEPARATED_STRING = "%s&%s&%s";
+
+ /**
+ * {@inheritDoc}
+ */
+ public String extract(OAuthRequest request)
+ {
+ checkPreconditions(request);
+ String verb = OAuthEncoder.encode(request.getVerb().name());
+ String url = OAuthEncoder.encode(request.getSanitizedUrl());
+ String params = getSortedAndEncodedParams(request);
+ return String.format(AMPERSAND_SEPARATED_STRING, verb, url, params);
+ }
+
+ private String getSortedAndEncodedParams(OAuthRequest request)
+ {
+ ParameterList params = new ParameterList();
+ params.addAll(request.getQueryStringParams());
+ params.addAll(request.getBodyParams());
+ params.addAll(new ParameterList(request.getOauthParameters()));
+ return params.sort().asOauthBaseString();
+ }
+
+ private void checkPreconditions(OAuthRequest request)
+ {
+ Preconditions.checkNotNull(request, "Cannot extract base string from null object");
+
+ if (request.getOauthParameters() == null || request.getOauthParameters().size() <= 0)
+ {
+ throw new OAuthParametersMissingException(request);
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/HeaderExtractor.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/HeaderExtractor.java
new file mode 100644
index 0000000..2bc1f8b
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/HeaderExtractor.java
@@ -0,0 +1,19 @@
+package org.scribe.extractors;
+
+import org.scribe.model.*;
+
+/**
+ * Simple command object that generates an OAuth Authorization header to include in the request.
+ *
+ * @author Pablo Fernandez
+ */
+public interface HeaderExtractor
+{
+ /**
+ * Generates an OAuth 'Authorization' Http header to include in requests as the signature.
+ *
+ * @param request the OAuthRequest to inspect and generate the header
+ * @return the Http header value
+ */
+ String extract(OAuthRequest request);
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/HeaderExtractorImpl.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/HeaderExtractorImpl.java
new file mode 100644
index 0000000..85f4526
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/HeaderExtractorImpl.java
@@ -0,0 +1,58 @@
+package org.scribe.extractors;
+
+import java.util.*;
+
+import org.scribe.exceptions.*;
+import org.scribe.model.*;
+import org.scribe.utils.*;
+
+/**
+ * Default implementation of {@link HeaderExtractor}. Conforms to OAuth 1.0a
+ *
+ * @author Pablo Fernandez
+ *
+ */
+public class HeaderExtractorImpl implements HeaderExtractor
+{
+ private static final String PARAM_SEPARATOR = ", ";
+ private static final String PREAMBLE = "OAuth ";
+ public static final int ESTIMATED_PARAM_LENGTH = 20;
+
+ /**
+ * {@inheritDoc}
+ */
+ public String extract(OAuthRequest request)
+ {
+ checkPreconditions(request);
+ Map parameters = request.getOauthParameters();
+ StringBuilder header = new StringBuilder(parameters.size() * ESTIMATED_PARAM_LENGTH);
+ header.append(PREAMBLE);
+ for (Map.Entry entry : parameters.entrySet())
+ {
+ if(header.length() > PREAMBLE.length())
+ {
+ header.append(PARAM_SEPARATOR);
+ }
+ header.append(String.format("%s=\"%s\"", entry.getKey(), OAuthEncoder.encode(entry.getValue())));
+ }
+
+ if (request.getRealm() != null && !request.getRealm().isEmpty())
+ {
+ header.append(PARAM_SEPARATOR);
+ header.append(String.format("%s=\"%s\"", OAuthConstants.REALM, request.getRealm()));
+ }
+
+ return header.toString();
+ }
+
+ private void checkPreconditions(OAuthRequest request)
+ {
+ Preconditions.checkNotNull(request, "Cannot extract a header from a null object");
+
+ if (request.getOauthParameters() == null || request.getOauthParameters().size() <= 0)
+ {
+ throw new OAuthParametersMissingException(request);
+ }
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/JsonTokenExtractor.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/JsonTokenExtractor.java
new file mode 100644
index 0000000..b51091f
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/JsonTokenExtractor.java
@@ -0,0 +1,27 @@
+package org.scribe.extractors;
+
+import java.util.regex.*;
+
+import org.scribe.exceptions.*;
+import org.scribe.model.*;
+import org.scribe.utils.*;
+
+public class JsonTokenExtractor implements AccessTokenExtractor
+{
+ private Pattern accessTokenPattern = Pattern.compile("\"access_token\":\\s*\"(\\S*?)\"");
+
+ public Token extract(String response)
+ {
+ Preconditions.checkEmptyString(response, "Cannot extract a token from a null or empty String");
+ Matcher matcher = accessTokenPattern.matcher(response);
+ if(matcher.find())
+ {
+ return new Token(matcher.group(1), "", response);
+ }
+ else
+ {
+ throw new OAuthException("Cannot extract an access token. Response was: " + response);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/RequestTokenExtractor.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/RequestTokenExtractor.java
new file mode 100644
index 0000000..1830212
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/RequestTokenExtractor.java
@@ -0,0 +1,19 @@
+package org.scribe.extractors;
+
+import org.scribe.model.*;
+
+/**
+ * Simple command object that extracts a {@link Token} from a String
+ *
+ * @author Pablo Fernandez
+ */
+public interface RequestTokenExtractor
+{
+ /**
+ * Extracts the request token from the contents of an Http Response
+ *
+ * @param response the contents of the response
+ * @return OAuth access token
+ */
+ public Token extract(String response);
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/TokenExtractor20Impl.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/TokenExtractor20Impl.java
new file mode 100644
index 0000000..1eb22ad
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/TokenExtractor20Impl.java
@@ -0,0 +1,36 @@
+package org.scribe.extractors;
+
+import java.util.regex.*;
+
+import org.scribe.exceptions.*;
+import org.scribe.model.*;
+import org.scribe.utils.*;
+
+/**
+ * Default implementation of {@AccessTokenExtractor}. Conforms to OAuth 2.0
+ *
+ */
+public class TokenExtractor20Impl implements AccessTokenExtractor
+{
+ private static final String TOKEN_REGEX = "access_token=([^&]+)";
+ private static final String EMPTY_SECRET = "";
+
+ /**
+ * {@inheritDoc}
+ */
+ public Token extract(String response)
+ {
+ Preconditions.checkEmptyString(response, "Response body is incorrect. Can't extract a token from an empty string");
+
+ Matcher matcher = Pattern.compile(TOKEN_REGEX).matcher(response);
+ if (matcher.find())
+ {
+ String token = OAuthEncoder.decode(matcher.group(1));
+ return new Token(token, EMPTY_SECRET, response);
+ }
+ else
+ {
+ throw new OAuthException("Response body is incorrect. Can't extract a token from this: '" + response + "'", null);
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/TokenExtractorImpl.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/TokenExtractorImpl.java
new file mode 100644
index 0000000..ba1784b
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/extractors/TokenExtractorImpl.java
@@ -0,0 +1,44 @@
+package org.scribe.extractors;
+
+import java.util.regex.*;
+
+import org.scribe.exceptions.*;
+import org.scribe.model.*;
+import org.scribe.utils.*;
+
+/**
+ * Default implementation of {@RequestTokenExtractor} and {@AccessTokenExtractor}. Conforms to OAuth 1.0a
+ *
+ * The process for extracting access and request tokens is similar so this class can do both things.
+ *
+ * @author Pablo Fernandez
+ */
+public class TokenExtractorImpl implements RequestTokenExtractor, AccessTokenExtractor
+{
+ private static final Pattern TOKEN_REGEX = Pattern.compile("oauth_token=([^&]+)");
+ private static final Pattern SECRET_REGEX = Pattern.compile("oauth_token_secret=([^&]*)");
+
+ /**
+ * {@inheritDoc}
+ */
+ public Token extract(String response)
+ {
+ Preconditions.checkEmptyString(response, "Response body is incorrect. Can't extract a token from an empty string");
+ String token = extract(response, TOKEN_REGEX);
+ String secret = extract(response, SECRET_REGEX);
+ return new Token(token, secret, response);
+ }
+
+ private String extract(String response, Pattern p)
+ {
+ Matcher matcher = p.matcher(response);
+ if (matcher.find() && matcher.groupCount() >= 1)
+ {
+ return OAuthEncoder.decode(matcher.group(1));
+ }
+ else
+ {
+ throw new OAuthException("Response body is incorrect. Can't extract token and secret from this: '" + response + "'", null);
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/OAuthConfig.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/OAuthConfig.java
new file mode 100644
index 0000000..374c958
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/OAuthConfig.java
@@ -0,0 +1,79 @@
+package org.scribe.model;
+
+import java.io.*;
+
+/**
+ * Parameter object that groups OAuth config values
+ *
+ * @author Pablo Fernandez
+ */
+public class OAuthConfig
+{
+ private final String apiKey;
+ private final String apiSecret;
+ private final String callback;
+ private final SignatureType signatureType;
+ private final String scope;
+ private final OutputStream debugStream;
+
+ public OAuthConfig(String key, String secret)
+ {
+ this(key, secret, null, null, null, null);
+ }
+
+ public OAuthConfig(String key, String secret, String callback, SignatureType type, String scope, OutputStream stream)
+ {
+ this.apiKey = key;
+ this.apiSecret = secret;
+ this.callback = callback;
+ this.signatureType = type;
+ this.scope = scope;
+ this.debugStream = stream;
+ }
+
+ public String getApiKey()
+ {
+ return apiKey;
+ }
+
+ public String getApiSecret()
+ {
+ return apiSecret;
+ }
+
+ public String getCallback()
+ {
+ return callback;
+ }
+
+ public SignatureType getSignatureType()
+ {
+ return signatureType;
+ }
+
+ public String getScope()
+ {
+ return scope;
+ }
+
+ public boolean hasScope()
+ {
+ return scope != null;
+ }
+
+ public void log(String message)
+ {
+ if (debugStream != null)
+ {
+ message = message + "\n";
+ try
+ {
+ debugStream.write(message.getBytes("UTF8"));
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("there were problems while writting to the debug stream", e);
+ }
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/OAuthConstants.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/OAuthConstants.java
new file mode 100644
index 0000000..c442dee
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/OAuthConstants.java
@@ -0,0 +1,52 @@
+/*
+Copyright 2010 Pablo Fernandez
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ */
+package org.scribe.model;
+
+/**
+ * This class contains OAuth constants, used project-wide
+ *
+ * @author Pablo Fernandez
+ */
+public class OAuthConstants
+{
+ private OAuthConstants(){}
+
+ public static final String TIMESTAMP = "oauth_timestamp";
+ public static final String SIGN_METHOD = "oauth_signature_method";
+ public static final String SIGNATURE = "oauth_signature";
+ public static final String CONSUMER_SECRET = "oauth_consumer_secret";
+ public static final String CONSUMER_KEY = "oauth_consumer_key";
+ public static final String CALLBACK = "oauth_callback";
+ public static final String VERSION = "oauth_version";
+ public static final String NONCE = "oauth_nonce";
+ public static final String REALM = "realm";
+ public static final String PARAM_PREFIX = "oauth_";
+ public static final String TOKEN = "oauth_token";
+ public static final String TOKEN_SECRET = "oauth_token_secret";
+ public static final String OUT_OF_BAND = "oob";
+ public static final String VERIFIER = "oauth_verifier";
+ public static final String HEADER = "Authorization";
+ public static final Token EMPTY_TOKEN = new Token("", "");
+ public static final String SCOPE = "scope";
+
+ //OAuth 2.0
+ public static final String ACCESS_TOKEN = "access_token";
+ public static final String CLIENT_ID = "client_id";
+ public static final String CLIENT_SECRET = "client_secret";
+ public static final String REDIRECT_URI = "redirect_uri";
+ public static final String CODE = "code";
+
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/OAuthRequest.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/OAuthRequest.java
new file mode 100644
index 0000000..d3b2e5a
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/OAuthRequest.java
@@ -0,0 +1,80 @@
+package org.scribe.model;
+
+import java.util.*;
+
+/**
+ * The representation of an OAuth HttpRequest.
+ *
+ * Adds OAuth-related functionality to the {@link Request}
+ *
+ * @author Pablo Fernandez
+ */
+public class OAuthRequest extends Request
+{
+ private static final String OAUTH_PREFIX = "oauth_";
+ private Map oauthParameters;
+ private String realm;
+
+ /**
+ * Default constructor.
+ *
+ * @param verb Http verb/method
+ * @param url resource URL
+ */
+ public OAuthRequest(Verb verb, String url)
+ {
+ super(verb, url);
+ this.oauthParameters = new HashMap();
+ }
+
+ /**
+ * Adds an OAuth parameter.
+ *
+ * @param key name of the parameter
+ * @param value value of the parameter
+ *
+ * @throws IllegalArgumentException if the parameter is not an OAuth parameter
+ */
+ public void addOAuthParameter(String key, String value)
+ {
+ oauthParameters.put(checkKey(key), value);
+ }
+
+ private String checkKey(String key)
+ {
+ if (key.startsWith(OAUTH_PREFIX) || key.equals(OAuthConstants.SCOPE))
+ {
+ return key;
+ }
+ else
+ {
+ throw new IllegalArgumentException(String.format("OAuth parameters must either be '%s' or start with '%s'", OAuthConstants.SCOPE, OAUTH_PREFIX));
+ }
+ }
+
+ /**
+ * Returns the {@link Map} containing the key-value pair of parameters.
+ *
+ * @return parameters as map
+ */
+ public Map getOauthParameters()
+ {
+ return oauthParameters;
+ }
+
+ public void setRealm(String realm)
+ {
+ this.realm = realm;
+ }
+
+ public String getRealm()
+ {
+ return realm;
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("@OAuthRequest(%s, %s)", getVerb(), getUrl());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Parameter.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Parameter.java
new file mode 100644
index 0000000..f8f3b81
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Parameter.java
@@ -0,0 +1,47 @@
+package org.scribe.model;
+
+import org.scribe.utils.*;
+
+/**
+ * @author: Pablo Fernandez
+ */
+public class Parameter implements Comparable
+{
+ private static final String UTF = "UTF8";
+
+ private final String key;
+ private final String value;
+
+ public Parameter(String key, String value)
+ {
+ this.key = key;
+ this.value = value;
+ }
+
+ public String asUrlEncodedPair()
+ {
+ return OAuthEncoder.encode(key).concat("=").concat(OAuthEncoder.encode(value));
+ }
+
+ public boolean equals(Object other)
+ {
+ if(other == null) return false;
+ if(other == this) return true;
+ if(!(other instanceof Parameter)) return false;
+
+ Parameter otherParam = (Parameter) other;
+ return otherParam.key.equals(key) && otherParam.value.equals(value);
+ }
+
+ public int hashCode()
+ {
+ return key.hashCode() + value.hashCode();
+ }
+
+ public int compareTo(Parameter parameter)
+ {
+ int keyDiff = key.compareTo(parameter.key);
+
+ return keyDiff != 0 ? keyDiff : value.compareTo(parameter.value);
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/ParameterList.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/ParameterList.java
new file mode 100644
index 0000000..b365cba
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/ParameterList.java
@@ -0,0 +1,114 @@
+package org.scribe.model;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.scribe.utils.OAuthEncoder;
+import org.scribe.utils.Preconditions;
+
+/**
+ * @author: Pablo Fernandez
+ */
+public class ParameterList
+{
+ private static final char QUERY_STRING_SEPARATOR = '?';
+ private static final String PARAM_SEPARATOR = "&";
+ private static final String PAIR_SEPARATOR = "=";
+ private static final String EMPTY_STRING = "";
+
+ private final List params;
+
+ public ParameterList()
+ {
+ params = new ArrayList();
+ }
+
+ ParameterList(List params)
+ {
+ this.params = new ArrayList(params);
+ }
+
+ public ParameterList(Map map)
+ {
+ this();
+ for(Map.Entry entry : map.entrySet())
+ {
+ params.add(new Parameter(entry.getKey(), entry.getValue()));
+ }
+ }
+
+ public void add(String key, String value)
+ {
+ params.add(new Parameter(key, value));
+ }
+
+ public String appendTo(String url)
+ {
+ Preconditions.checkNotNull(url, "Cannot append to null URL");
+ String queryString = asFormUrlEncodedString();
+ if (queryString.equals(EMPTY_STRING))
+ {
+ return url;
+ }
+ else
+ {
+ url += url.indexOf(QUERY_STRING_SEPARATOR) != -1 ? PARAM_SEPARATOR : QUERY_STRING_SEPARATOR;
+ url += queryString;
+ return url;
+ }
+ }
+
+ public String asOauthBaseString()
+ {
+ return OAuthEncoder.encode(asFormUrlEncodedString());
+ }
+
+ public String asFormUrlEncodedString()
+ {
+ if (params.size() == 0) return EMPTY_STRING;
+
+ StringBuilder builder = new StringBuilder();
+ for(Parameter p : params)
+ {
+ builder.append('&').append(p.asUrlEncodedPair());
+ }
+ return builder.toString().substring(1);
+ }
+
+ public void addAll(ParameterList other)
+ {
+ params.addAll(other.params);
+ }
+
+ public void addQuerystring(String queryString)
+ {
+ if (queryString != null && queryString.length() > 0)
+ {
+ for (String param : queryString.split(PARAM_SEPARATOR))
+ {
+ String pair[] = param.split(PAIR_SEPARATOR);
+ String key = OAuthEncoder.decode(pair[0]);
+ String value = pair.length > 1 ? OAuthEncoder.decode(pair[1]) : EMPTY_STRING;
+ params.add(new Parameter(key, value));
+ }
+ }
+ }
+
+ public boolean contains(Parameter param)
+ {
+ return params.contains(param);
+ }
+
+ public int size()
+ {
+ return params.size();
+ }
+
+ public ParameterList sort()
+ {
+ ParameterList sorted = new ParameterList(params);
+ Collections.sort(sorted.params);
+ return sorted;
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Request.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Request.java
new file mode 100644
index 0000000..e48578e
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Request.java
@@ -0,0 +1,390 @@
+package org.scribe.model;
+
+import java.io.*;
+import java.net.*;
+import java.nio.charset.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.scribe.exceptions.*;
+
+/**
+ * Represents an HTTP Request object
+ *
+ * @author Pablo Fernandez
+ */
+public class Request
+{
+ private static final String CONTENT_LENGTH = "Content-Length";
+ private static final String CONTENT_TYPE = "Content-Type";
+ private static RequestTuner NOOP = new RequestTuner() {
+ @Override public void tune(Request _){}
+ };
+ public static final String DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded";
+
+ private String url;
+ private Verb verb;
+ private ParameterList querystringParams;
+ private ParameterList bodyParams;
+ private Map headers;
+ private String payload = null;
+ private HttpURLConnection connection;
+ private String charset;
+ private byte[] bytePayload = null;
+ private boolean connectionKeepAlive = false;
+ private boolean followRedirects = true;
+ private Long connectTimeout = null;
+ private Long readTimeout = null;
+
+ /**
+ * Creates a new Http Request
+ *
+ * @param verb Http Verb (GET, POST, etc)
+ * @param url url with optional querystring parameters.
+ */
+ public Request(Verb verb, String url)
+ {
+ this.verb = verb;
+ this.url = url;
+ this.querystringParams = new ParameterList();
+ this.bodyParams = new ParameterList();
+ this.headers = new HashMap();
+ }
+
+ /**
+ * Execute the request and return a {@link Response}
+ *
+ * @return Http Response
+ * @throws RuntimeException
+ * if the connection cannot be created.
+ */
+ public Response send(RequestTuner tuner)
+ {
+ try
+ {
+ createConnection();
+ return doSend(tuner);
+ }
+ catch (Exception e)
+ {
+ throw new OAuthConnectionException(e);
+ }
+ }
+
+ public Response send()
+ {
+ return send(NOOP);
+ }
+
+ private void createConnection() throws IOException
+ {
+ String completeUrl = getCompleteUrl();
+ if (connection == null)
+ {
+ System.setProperty("http.keepAlive", connectionKeepAlive ? "true" : "false");
+ connection = (HttpURLConnection) new URL(completeUrl).openConnection();
+ connection.setInstanceFollowRedirects(followRedirects);
+ }
+ }
+
+ /**
+ * Returns the complete url (host + resource + encoded querystring parameters).
+ *
+ * @return the complete url.
+ */
+ public String getCompleteUrl()
+ {
+ return querystringParams.appendTo(url);
+ }
+
+ Response doSend(RequestTuner tuner) throws IOException
+ {
+ connection.setRequestMethod(this.verb.name());
+ if (connectTimeout != null)
+ {
+ connection.setConnectTimeout(connectTimeout.intValue());
+ }
+ if (readTimeout != null)
+ {
+ connection.setReadTimeout(readTimeout.intValue());
+ }
+ addHeaders(connection);
+ if (verb.equals(Verb.PUT) || verb.equals(Verb.POST))
+ {
+ addBody(connection, getByteBodyContents());
+ }
+ tuner.tune(this);
+ return new Response(connection);
+ }
+
+ void addHeaders(HttpURLConnection conn)
+ {
+ for (String key : headers.keySet())
+ conn.setRequestProperty(key, headers.get(key));
+ }
+
+ void addBody(HttpURLConnection conn, byte[] content) throws IOException
+ {
+ conn.setRequestProperty(CONTENT_LENGTH, String.valueOf(content.length));
+
+ // Set default content type if none is set.
+ if (conn.getRequestProperty(CONTENT_TYPE) == null)
+ {
+ conn.setRequestProperty(CONTENT_TYPE, DEFAULT_CONTENT_TYPE);
+ }
+ conn.setDoOutput(true);
+ conn.getOutputStream().write(content);
+ }
+
+ /**
+ * Add an HTTP Header to the Request
+ *
+ * @param key the header name
+ * @param value the header value
+ */
+ public void addHeader(String key, String value)
+ {
+ this.headers.put(key, value);
+ }
+
+ /**
+ * Add a body Parameter (for POST/ PUT Requests)
+ *
+ * @param key the parameter name
+ * @param value the parameter value
+ */
+ public void addBodyParameter(String key, String value)
+ {
+ this.bodyParams.add(key, value);
+ }
+
+ /**
+ * Add a QueryString parameter
+ *
+ * @param key the parameter name
+ * @param value the parameter value
+ */
+ public void addQuerystringParameter(String key, String value)
+ {
+ this.querystringParams.add(key, value);
+ }
+
+ /**
+ * Add body payload.
+ *
+ * This method is used when the HTTP body is not a form-url-encoded string,
+ * but another thing. Like for example XML.
+ *
+ * Note: The contents are not part of the OAuth signature
+ *
+ * @param payload the body of the request
+ */
+ public void addPayload(String payload)
+ {
+ this.payload = payload;
+ }
+
+ /**
+ * Overloaded version for byte arrays
+ *
+ * @param payload
+ */
+ public void addPayload(byte[] payload)
+ {
+ this.bytePayload = payload.clone();
+ }
+
+ /**
+ * Get a {@link ParameterList} with the query string parameters.
+ *
+ * @return a {@link ParameterList} containing the query string parameters.
+ * @throws OAuthException if the request URL is not valid.
+ */
+ public ParameterList getQueryStringParams()
+ {
+ try
+ {
+ ParameterList result = new ParameterList();
+ String queryString = new URL(url).getQuery();
+ result.addQuerystring(queryString);
+ result.addAll(querystringParams);
+ return result;
+ }
+ catch (MalformedURLException mue)
+ {
+ throw new OAuthException("Malformed URL", mue);
+ }
+ }
+
+ /**
+ * Obtains a {@link ParameterList} of the body parameters.
+ *
+ * @return a {@link ParameterList}containing the body parameters.
+ */
+ public ParameterList getBodyParams()
+ {
+ return bodyParams;
+ }
+
+ /**
+ * Obtains the URL of the HTTP Request.
+ *
+ * @return the original URL of the HTTP Request
+ */
+ public String getUrl()
+ {
+ return url;
+ }
+
+ /**
+ * Returns the URL without the default port and the query string part.
+ *
+ * @return the OAuth-sanitized URL
+ */
+ public String getSanitizedUrl()
+ {
+ if(url.startsWith("http://") && (url.endsWith(":80") || url.contains(":80/"))){
+ return url.replaceAll("\\?.*", "").replaceAll(":80", "");
+ }
+ else if(url.startsWith("https://") && (url.endsWith(":443") || url.contains(":443/"))){
+ return url.replaceAll("\\?.*", "").replaceAll(":443", "");
+ }
+ else{
+ return url.replaceAll("\\?.*", "");
+ }
+ }
+
+ /**
+ * Returns the body of the request
+ *
+ * @return form encoded string
+ * @throws OAuthException if the charset chosen is not supported
+ */
+ public String getBodyContents()
+ {
+ try
+ {
+ return new String(getByteBodyContents(),getCharset());
+ }
+ catch(UnsupportedEncodingException uee)
+ {
+ throw new OAuthException("Unsupported Charset: "+charset, uee);
+ }
+ }
+
+ byte[] getByteBodyContents()
+ {
+ if (bytePayload != null) return bytePayload;
+ String body = (payload != null) ? payload : bodyParams.asFormUrlEncodedString();
+ try
+ {
+ return body.getBytes(getCharset());
+ }
+ catch(UnsupportedEncodingException uee)
+ {
+ throw new OAuthException("Unsupported Charset: "+getCharset(), uee);
+ }
+ }
+
+ /**
+ * Returns the HTTP Verb
+ *
+ * @return the verb
+ */
+ public Verb getVerb()
+ {
+ return verb;
+ }
+
+ /**
+ * Returns the connection headers as a {@link Map}
+ *
+ * @return map of headers
+ */
+ public Map getHeaders()
+ {
+ return headers;
+ }
+
+ /**
+ * Returns the connection charset. Defaults to {@link Charset} defaultCharset if not set
+ *
+ * @return charset
+ */
+ public String getCharset()
+ {
+ return charset == null ? Charset.defaultCharset().name() : charset;
+ }
+
+ /**
+ * Sets the connect timeout for the underlying {@link HttpURLConnection}
+ *
+ * @param duration duration of the timeout
+ *
+ * @param unit unit of time (milliseconds, seconds, etc)
+ */
+ public void setConnectTimeout(int duration, TimeUnit unit)
+ {
+ this.connectTimeout = unit.toMillis(duration);
+ }
+
+ /**
+ * Sets the read timeout for the underlying {@link HttpURLConnection}
+ *
+ * @param duration duration of the timeout
+ *
+ * @param unit unit of time (milliseconds, seconds, etc)
+ */
+ public void setReadTimeout(int duration, TimeUnit unit)
+ {
+ this.readTimeout = unit.toMillis(duration);
+ }
+
+ /**
+ * Set the charset of the body of the request
+ *
+ * @param charsetName name of the charset of the request
+ */
+ public void setCharset(String charsetName)
+ {
+ this.charset = charsetName;
+ }
+
+ /**
+ * Sets whether the underlying Http Connection is persistent or not.
+ *
+ * @see http://download.oracle.com/javase/1.5.0/docs/guide/net/http-keepalive.html
+ * @param connectionKeepAlive
+ */
+ public void setConnectionKeepAlive(boolean connectionKeepAlive)
+ {
+ this.connectionKeepAlive = connectionKeepAlive;
+ }
+
+ /**
+ * Sets whether the underlying Http Connection follows redirects or not.
+ *
+ * Defaults to true (follow redirects)
+ *
+ * @see http://docs.oracle.com/javase/6/docs/api/java/net/HttpURLConnection.html#setInstanceFollowRedirects(boolean)
+ * @param followRedirects
+ */
+ public void setFollowRedirects(boolean followRedirects)
+ {
+ this.followRedirects = followRedirects;
+ }
+
+ /*
+ * We need this in order to stub the connection object for test cases
+ */
+ void setConnection(HttpURLConnection connection)
+ {
+ this.connection = connection;
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("@Request(%s %s)", getVerb(), getUrl());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/RequestTuner.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/RequestTuner.java
new file mode 100644
index 0000000..34ea1eb
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/RequestTuner.java
@@ -0,0 +1,6 @@
+package org.scribe.model;
+
+public abstract class RequestTuner
+{
+ public abstract void tune(Request request);
+}
\ No newline at end of file
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Response.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Response.java
new file mode 100644
index 0000000..d433922
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Response.java
@@ -0,0 +1,126 @@
+package org.scribe.model;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import org.scribe.exceptions.*;
+import org.scribe.utils.*;
+
+/**
+ * Represents an HTTP Response.
+ *
+ * @author Pablo Fernandez
+ */
+public class Response
+{
+ private static final String EMPTY = "";
+
+ private int code;
+ private String message;
+ private String body;
+ private InputStream stream;
+ private Map headers;
+
+ Response(HttpURLConnection connection) throws IOException
+ {
+ try
+ {
+ connection.connect();
+ code = connection.getResponseCode();
+ message = connection.getResponseMessage();
+ headers = parseHeaders(connection);
+ stream = isSuccessful() ? connection.getInputStream() : connection.getErrorStream();
+ }
+ catch (UnknownHostException e)
+ {
+ throw new OAuthException("The IP address of a host could not be determined.", e);
+ }
+ }
+
+ private String parseBodyContents()
+ {
+ body = StreamUtils.getStreamContents(getStream());
+ return body;
+ }
+
+ private Map parseHeaders(HttpURLConnection conn)
+ {
+ Map headers = new HashMap();
+ for (String key : conn.getHeaderFields().keySet())
+ {
+ headers.put(key, conn.getHeaderFields().get(key).get(0));
+ }
+ return headers;
+ }
+
+ public boolean isSuccessful()
+ {
+ return getCode() >= 200 && getCode() < 400;
+ }
+
+ /**
+ * Obtains the HTTP Response body
+ *
+ * @return response body
+ */
+ public String getBody()
+ {
+ return body != null ? body : parseBodyContents();
+ }
+
+ /**
+ * Obtains the meaningful stream of the HttpUrlConnection, either inputStream
+ * or errorInputStream, depending on the status code
+ *
+ * @return input stream / error stream
+ */
+ public InputStream getStream()
+ {
+ return stream;
+ }
+
+ /**
+ * Obtains the HTTP status code
+ *
+ * @return the status code
+ */
+ public int getCode()
+ {
+ return code;
+ }
+
+ /**
+ * Obtains the HTTP status message.
+ * Returns null if the message can not be discerned from the response (not valid HTTP)
+ *
+ * @return the status message
+ */
+ public String getMessage()
+ {
+ return message;
+ }
+
+ /**
+ * Obtains a {@link Map} containing the HTTP Response Headers
+ *
+ * @return headers
+ */
+ public Map getHeaders()
+ {
+ return headers;
+ }
+
+ /**
+ * Obtains a single HTTP Header value, or null if undefined
+ *
+ * @param name the header name.
+ *
+ * @return header value or null.
+ */
+ public String getHeader(String name)
+ {
+ return headers.get(name);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/SignatureType.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/SignatureType.java
new file mode 100644
index 0000000..3440a36
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/SignatureType.java
@@ -0,0 +1,7 @@
+package org.scribe.model;
+
+public enum SignatureType
+{
+ Header,
+ QueryString
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Token.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Token.java
new file mode 100644
index 0000000..4d8c0ee
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Token.java
@@ -0,0 +1,98 @@
+package org.scribe.model;
+
+import java.io.*;
+import org.scribe.utils.*;
+
+/**
+ * Represents an OAuth token (either request or access token) and its secret
+ *
+ * @author Pablo Fernandez
+ */
+public class Token implements Serializable
+{
+ private static final long serialVersionUID = 715000866082812683L;
+
+ private final String token;
+ private final String secret;
+ private final String rawResponse;
+
+ /**
+ * Default constructor
+ *
+ * @param token token value. Can't be null.
+ * @param secret token secret. Can't be null.
+ */
+ public Token(String token, String secret)
+ {
+ this(token, secret, null);
+ }
+
+ public Token(String token, String secret, String rawResponse)
+ {
+ Preconditions.checkNotNull(token, "Token can't be null");
+ Preconditions.checkNotNull(secret, "Secret can't be null");
+
+ this.token = token;
+ this.secret = secret;
+ this.rawResponse = rawResponse;
+ }
+
+ public String getToken()
+ {
+ return token;
+ }
+
+ public String getSecret()
+ {
+ return secret;
+ }
+
+ public String getRawResponse()
+ {
+ if (rawResponse == null)
+ {
+ throw new IllegalStateException("This token object was not constructed by scribe and does not have a rawResponse");
+ }
+ return rawResponse;
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("Token[%s , %s]", token, secret);
+ }
+
+ /**
+ * Returns true if the token is empty (token = "", secret = "")
+ */
+ public boolean isEmpty()
+ {
+ return "".equals(this.token) && "".equals(this.secret);
+ }
+
+ /**
+ * Factory method that returns an empty token (token = "", secret = "").
+ *
+ * Useful for two legged OAuth.
+ */
+ public static Token empty()
+ {
+ return new Token("", "");
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Token that = (Token) o;
+ return token.equals(that.token) && secret.equals(that.secret);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return 31 * token.hashCode() + secret.hashCode();
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Verb.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Verb.java
new file mode 100644
index 0000000..ec05731
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Verb.java
@@ -0,0 +1,11 @@
+package org.scribe.model;
+
+/**
+ * An enumeration containing the most common HTTP Verbs.
+ *
+ * @author Pablo Fernandez
+ */
+public enum Verb
+{
+ GET, POST, PUT, DELETE, HEAD, OPTIONS, TRACE
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Verifier.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Verifier.java
new file mode 100644
index 0000000..45f0e4e
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/model/Verifier.java
@@ -0,0 +1,30 @@
+package org.scribe.model;
+
+import org.scribe.utils.*;
+
+/**
+ * Represents an OAuth verifier code.
+ *
+ * @author Pablo Fernandez
+ */
+public class Verifier
+{
+
+ private final String value;
+
+ /**
+ * Default constructor.
+ *
+ * @param value verifier value
+ */
+ public Verifier(String value)
+ {
+ Preconditions.checkNotNull(value, "Must provide a valid string as verifier");
+ this.value = value;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/oauth/OAuth10aServiceImpl.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/oauth/OAuth10aServiceImpl.java
new file mode 100644
index 0000000..2b207f5
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/oauth/OAuth10aServiceImpl.java
@@ -0,0 +1,196 @@
+package org.scribe.oauth;
+
+import java.util.*;
+
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.services.*;
+import org.scribe.utils.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * OAuth 1.0a implementation of {@link OAuthService}
+ *
+ * @author Pablo Fernandez
+ */
+public class OAuth10aServiceImpl implements OAuthService
+{
+ private static final String VERSION = "1.0";
+
+ private OAuthConfig config;
+ private DefaultApi10a api;
+
+ /**
+ * Default constructor
+ *
+ * @param api OAuth1.0a api information
+ * @param config OAuth 1.0a configuration param object
+ */
+ public OAuth10aServiceImpl(DefaultApi10a api, OAuthConfig config)
+ {
+ this.api = api;
+ this.config = config;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Token getRequestToken(int timeout, TimeUnit unit)
+ {
+ return getRequestToken(new TimeoutTuner(timeout, unit));
+ }
+
+ public Token getRequestToken()
+ {
+ return getRequestToken(2, TimeUnit.SECONDS);
+ }
+
+ public Token getRequestToken(RequestTuner tuner)
+ {
+ config.log("obtaining request token from " + api.getRequestTokenEndpoint());
+ OAuthRequest request = new OAuthRequest(api.getRequestTokenVerb(), api.getRequestTokenEndpoint());
+
+ config.log("setting oauth_callback to " + config.getCallback());
+ request.addOAuthParameter(OAuthConstants.CALLBACK, config.getCallback());
+ addOAuthParams(request, OAuthConstants.EMPTY_TOKEN);
+ appendSignature(request);
+
+ config.log("sending request...");
+ Response response = request.send(tuner);
+ String body = response.getBody();
+
+ config.log("response status code: " + response.getCode());
+ config.log("response body: " + body);
+ return api.getRequestTokenExtractor().extract(body);
+ }
+
+ private void addOAuthParams(OAuthRequest request, Token token)
+ {
+ request.addOAuthParameter(OAuthConstants.TIMESTAMP, api.getTimestampService().getTimestampInSeconds());
+ request.addOAuthParameter(OAuthConstants.NONCE, api.getTimestampService().getNonce());
+ request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, config.getApiKey());
+ request.addOAuthParameter(OAuthConstants.SIGN_METHOD, api.getSignatureService().getSignatureMethod());
+ request.addOAuthParameter(OAuthConstants.VERSION, getVersion());
+ if(config.hasScope()) request.addOAuthParameter(OAuthConstants.SCOPE, config.getScope());
+ request.addOAuthParameter(OAuthConstants.SIGNATURE, getSignature(request, token));
+
+ config.log("appended additional OAuth parameters: " + MapUtils.toString(request.getOauthParameters()));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Token getAccessToken(Token requestToken, Verifier verifier, int timeout, TimeUnit unit)
+ {
+ return getAccessToken(requestToken, verifier, new TimeoutTuner(timeout, unit));
+ }
+
+ public Token getAccessToken(Token requestToken, Verifier verifier)
+ {
+ return getAccessToken(requestToken, verifier, 2, TimeUnit.SECONDS);
+ }
+
+ public Token getAccessToken(Token requestToken, Verifier verifier, RequestTuner tuner)
+ {
+ config.log("obtaining access token from " + api.getAccessTokenEndpoint());
+ OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint());
+ request.addOAuthParameter(OAuthConstants.TOKEN, requestToken.getToken());
+ request.addOAuthParameter(OAuthConstants.VERIFIER, verifier.getValue());
+
+ config.log("setting token to: " + requestToken + " and verifier to: " + verifier);
+ addOAuthParams(request, requestToken);
+ appendSignature(request);
+
+ config.log("sending request...");
+ Response response = request.send(tuner);
+ String body = response.getBody();
+
+ config.log("response status code: " + response.getCode());
+ config.log("response body: " + body);
+ return api.getAccessTokenExtractor().extract(body);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void signRequest(Token token, OAuthRequest request)
+ {
+ config.log("signing request: " + request.getCompleteUrl());
+
+ // Do not append the token if empty. This is for two legged OAuth calls.
+ if (!token.isEmpty())
+ {
+ request.addOAuthParameter(OAuthConstants.TOKEN, token.getToken());
+ }
+ config.log("setting token to: " + token);
+ addOAuthParams(request, token);
+ appendSignature(request);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getVersion()
+ {
+ return VERSION;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return api.getAuthorizationUrl(requestToken);
+ }
+
+ private String getSignature(OAuthRequest request, Token token)
+ {
+ config.log("generating signature...");
+ config.log("using base64 encoder: " + Base64Encoder.type());
+ String baseString = api.getBaseStringExtractor().extract(request);
+ String signature = api.getSignatureService().getSignature(baseString, config.getApiSecret(), token.getSecret());
+
+ config.log("base string is: " + baseString);
+ config.log("signature is: " + signature);
+ return signature;
+ }
+
+ private void appendSignature(OAuthRequest request)
+ {
+ switch (config.getSignatureType())
+ {
+ case Header:
+ config.log("using Http Header signature");
+
+ String oauthHeader = api.getHeaderExtractor().extract(request);
+ request.addHeader(OAuthConstants.HEADER, oauthHeader);
+ break;
+ case QueryString:
+ config.log("using Querystring signature");
+
+ for (Map.Entry entry : request.getOauthParameters().entrySet())
+ {
+ request.addQuerystringParameter(entry.getKey(), entry.getValue());
+ }
+ break;
+ }
+ }
+
+ private static class TimeoutTuner extends RequestTuner
+ {
+ private final int duration;
+ private final TimeUnit unit;
+
+ public TimeoutTuner(int duration, TimeUnit unit)
+ {
+ this.duration = duration;
+ this.unit = unit;
+ }
+
+ @Override
+ public void tune(Request request)
+ {
+ request.setReadTimeout(duration, unit);
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/oauth/OAuth20ServiceImpl.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/oauth/OAuth20ServiceImpl.java
new file mode 100644
index 0000000..6262c37
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/oauth/OAuth20ServiceImpl.java
@@ -0,0 +1,72 @@
+package org.scribe.oauth;
+
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+
+public class OAuth20ServiceImpl implements OAuthService
+{
+ private static final String VERSION = "2.0";
+
+ private final DefaultApi20 api;
+ private final OAuthConfig config;
+
+ /**
+ * Default constructor
+ *
+ * @param api OAuth2.0 api information
+ * @param config OAuth 2.0 configuration param object
+ */
+ public OAuth20ServiceImpl(DefaultApi20 api, OAuthConfig config)
+ {
+ this.api = api;
+ this.config = config;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Token getAccessToken(Token requestToken, Verifier verifier)
+ {
+ OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint());
+ request.addQuerystringParameter(OAuthConstants.CLIENT_ID, config.getApiKey());
+ request.addQuerystringParameter(OAuthConstants.CLIENT_SECRET, config.getApiSecret());
+ request.addQuerystringParameter(OAuthConstants.CODE, verifier.getValue());
+ request.addQuerystringParameter(OAuthConstants.REDIRECT_URI, config.getCallback());
+ if(config.hasScope()) request.addQuerystringParameter(OAuthConstants.SCOPE, config.getScope());
+ Response response = request.send();
+ return api.getAccessTokenExtractor().extract(response.getBody());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Token getRequestToken()
+ {
+ throw new UnsupportedOperationException("Unsupported operation, please use 'getAuthorizationUrl' and redirect your users there");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getVersion()
+ {
+ return VERSION;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void signRequest(Token accessToken, OAuthRequest request)
+ {
+ request.addQuerystringParameter(OAuthConstants.ACCESS_TOKEN, accessToken.getToken());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getAuthorizationUrl(Token requestToken)
+ {
+ return api.getAuthorizationUrl(config);
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/oauth/OAuthService.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/oauth/OAuthService.java
new file mode 100644
index 0000000..0c9c57e
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/oauth/OAuthService.java
@@ -0,0 +1,53 @@
+package org.scribe.oauth;
+
+import org.scribe.model.*;
+
+/**
+ * The main Scribe object.
+ *
+ * A facade responsible for the retrieval of request and access tokens and for the signing of HTTP requests.
+ *
+ * @author Pablo Fernandez
+ */
+public interface OAuthService
+{
+ /**
+ * Retrieve the request token.
+ *
+ * @return request token
+ */
+ public Token getRequestToken();
+
+ /**
+ * Retrieve the access token
+ *
+ * @param requestToken request token (obtained previously)
+ * @param verifier verifier code
+ * @return access token
+ */
+ public Token getAccessToken(Token requestToken, Verifier verifier);
+
+ /**
+ * Signs am OAuth request
+ *
+ * @param accessToken access token (obtained previously)
+ * @param request request to sign
+ */
+ public void signRequest(Token accessToken, OAuthRequest request);
+
+ /**
+ * Returns the OAuth version of the service.
+ *
+ * @return oauth version as string
+ */
+ public String getVersion();
+
+ /**
+ * Returns the URL where you should redirect your users to authenticate
+ * your application.
+ *
+ * @param requestToken the request token you need to authorize
+ * @return the URL where you should redirect your users
+ */
+ public String getAuthorizationUrl(Token requestToken);
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/Base64Encoder.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/Base64Encoder.java
new file mode 100644
index 0000000..4a091c1
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/Base64Encoder.java
@@ -0,0 +1,36 @@
+package org.scribe.services;
+
+public abstract class Base64Encoder
+{
+ private static Base64Encoder instance;
+
+ public static synchronized Base64Encoder getInstance()
+ {
+ if (instance == null)
+ {
+ instance = createEncoderInstance();
+ }
+ return instance;
+ }
+
+ private static Base64Encoder createEncoderInstance()
+ {
+ if (CommonsEncoder.isPresent())
+ {
+ return new CommonsEncoder();
+ }
+ else
+ {
+ return new DatatypeConverterEncoder();
+ }
+ }
+
+ public static String type()
+ {
+ return getInstance().getType();
+ }
+
+ public abstract String encode(byte[] bytes);
+
+ public abstract String getType();
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/CommonsEncoder.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/CommonsEncoder.java
new file mode 100644
index 0000000..4269a69
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/CommonsEncoder.java
@@ -0,0 +1,42 @@
+package org.scribe.services;
+
+import org.apache.commons.codec.binary.*;
+import org.scribe.exceptions.*;
+
+import java.io.UnsupportedEncodingException;
+
+public class CommonsEncoder extends Base64Encoder
+{
+
+ @Override
+ public String encode(byte[] bytes)
+ {
+ try
+ {
+ return new String(Base64.encodeBase64(bytes), "UTF-8");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new OAuthSignatureException("Can't perform base64 encoding", e);
+ }
+ }
+
+ @Override
+ public String getType()
+ {
+ return "CommonsCodec";
+ }
+
+ public static boolean isPresent()
+ {
+ try
+ {
+ Class.forName("org.apache.commons.codec.binary.Base64");
+ return true;
+ }
+ catch (ClassNotFoundException e)
+ {
+ return false;
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/DatatypeConverterEncoder.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/DatatypeConverterEncoder.java
new file mode 100644
index 0000000..d147eba
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/DatatypeConverterEncoder.java
@@ -0,0 +1,18 @@
+package org.scribe.services;
+
+import javax.xml.bind.*;
+
+public class DatatypeConverterEncoder extends Base64Encoder
+{
+ @Override
+ public String encode(byte[] bytes)
+ {
+ return DatatypeConverter.printBase64Binary(bytes);
+ }
+
+ @Override
+ public String getType()
+ {
+ return "DatatypeConverter";
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/HMACSha1SignatureService.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/HMACSha1SignatureService.java
new file mode 100644
index 0000000..560c2e6
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/HMACSha1SignatureService.java
@@ -0,0 +1,61 @@
+package org.scribe.services;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+import org.scribe.exceptions.*;
+import org.scribe.utils.*;
+
+/**
+ * HMAC-SHA1 implementation of {@SignatureService}
+ *
+ * @author Pablo Fernandez
+ *
+ */
+public class HMACSha1SignatureService implements SignatureService
+{
+ private static final String EMPTY_STRING = "";
+ private static final String CARRIAGE_RETURN = "\r\n";
+ private static final String UTF8 = "UTF-8";
+ private static final String HMAC_SHA1 = "HmacSHA1";
+ private static final String METHOD = "HMAC-SHA1";
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getSignature(String baseString, String apiSecret, String tokenSecret)
+ {
+ try
+ {
+ Preconditions.checkEmptyString(baseString, "Base string cant be null or empty string");
+ Preconditions.checkEmptyString(apiSecret, "Api secret cant be null or empty string");
+ return doSign(baseString, OAuthEncoder.encode(apiSecret) + '&' + OAuthEncoder.encode(tokenSecret));
+ }
+ catch (Exception e)
+ {
+ throw new OAuthSignatureException(baseString, e);
+ }
+ }
+
+ private String doSign(String toSign, String keyString) throws Exception
+ {
+ SecretKeySpec key = new SecretKeySpec((keyString).getBytes(UTF8), HMAC_SHA1);
+ Mac mac = Mac.getInstance(HMAC_SHA1);
+ mac.init(key);
+ byte[] bytes = mac.doFinal(toSign.getBytes(UTF8));
+ return bytesToBase64String(bytes).replace(CARRIAGE_RETURN, EMPTY_STRING);
+ }
+
+ private String bytesToBase64String(byte[] bytes)
+ {
+ return Base64Encoder.getInstance().encode(bytes);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getSignatureMethod()
+ {
+ return METHOD;
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/PlaintextSignatureService.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/PlaintextSignatureService.java
new file mode 100644
index 0000000..03306e8
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/PlaintextSignatureService.java
@@ -0,0 +1,40 @@
+package org.scribe.services;
+
+import org.scribe.exceptions.*;
+import org.scribe.utils.*;
+
+/**
+ * plaintext implementation of {@SignatureService}
+ *
+ * @author Pablo Fernandez
+ *
+ */
+public class PlaintextSignatureService implements SignatureService
+{
+ private static final String METHOD = "PLAINTEXT";
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getSignature(String baseString, String apiSecret, String tokenSecret)
+ {
+ try
+ {
+ Preconditions.checkEmptyString(apiSecret, "Api secret cant be null or empty string");
+ return OAuthEncoder.encode(apiSecret) + '&' + OAuthEncoder.encode(tokenSecret);
+ }
+ catch (Exception e)
+ {
+ throw new OAuthSignatureException(baseString, e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getSignatureMethod()
+ {
+ return METHOD;
+ }
+}
+
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/RSASha1SignatureService.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/RSASha1SignatureService.java
new file mode 100644
index 0000000..c427611
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/RSASha1SignatureService.java
@@ -0,0 +1,52 @@
+package org.scribe.services;
+
+import org.scribe.exceptions.*;
+import java.security.*;
+
+/**
+ * A signature service that uses the RSA-SHA1 algorithm.
+ */
+public class RSASha1SignatureService implements SignatureService
+{
+ private static final String METHOD = "RSA-SHA1";
+ private static final String RSA_SHA1 = "SHA1withRSA";
+ private static final String UTF8 = "UTF-8";
+
+ private PrivateKey privateKey;
+
+ public RSASha1SignatureService(PrivateKey privateKey)
+ {
+ this.privateKey = privateKey;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getSignature(String baseString, String apiSecret, String tokenSecret)
+ {
+ try
+ {
+ Signature signature = Signature.getInstance(RSA_SHA1);
+ signature.initSign(privateKey);
+ signature.update(baseString.getBytes(UTF8));
+ return bytesToBase64String(signature);
+ }
+ catch (Exception e)
+ {
+ throw new OAuthSignatureException(baseString, e);
+ }
+ }
+
+ private String bytesToBase64String(Signature signature) throws SignatureException
+ {
+ return Base64Encoder.getInstance().encode(signature.sign());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getSignatureMethod()
+ {
+ return METHOD;
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/SignatureService.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/SignatureService.java
new file mode 100644
index 0000000..229c2f6
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/SignatureService.java
@@ -0,0 +1,28 @@
+package org.scribe.services;
+
+/**
+ * Signs a base string, returning the OAuth signature
+ *
+ * @author Pablo Fernandez
+ *
+ */
+public interface SignatureService
+{
+ /**
+ * Returns the signature
+ *
+ * @param baseString url-encoded string to sign
+ * @param apiSecret api secret for your app
+ * @param tokenSecret token secret (empty string for the request token step)
+ *
+ * @return signature
+ */
+ public String getSignature(String baseString, String apiSecret, String tokenSecret);
+
+ /**
+ * Returns the signature method/algorithm
+ *
+ * @return
+ */
+ public String getSignatureMethod();
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/TimestampService.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/TimestampService.java
new file mode 100644
index 0000000..221a226
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/TimestampService.java
@@ -0,0 +1,25 @@
+package org.scribe.services;
+
+/**
+ * Unix epoch timestamp generator.
+ *
+ * This class is useful for stubbing in tests.
+ *
+ * @author Pablo Fernandez
+ */
+public interface TimestampService
+{
+ /**
+ * Returns the unix epoch timestamp in seconds
+ *
+ * @return timestamp
+ */
+ public String getTimestampInSeconds();
+
+ /**
+ * Returns a nonce (unique value for each request)
+ *
+ * @return nonce
+ */
+ public String getNonce();
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/TimestampServiceImpl.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/TimestampServiceImpl.java
new file mode 100644
index 0000000..486e93c
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/services/TimestampServiceImpl.java
@@ -0,0 +1,68 @@
+package org.scribe.services;
+
+import java.util.*;
+
+/**
+ * Implementation of {@link TimestampService} using plain java classes.
+ *
+ * @author Pablo Fernandez
+ */
+public class TimestampServiceImpl implements TimestampService
+{
+ private Timer timer;
+
+ /**
+ * Default constructor.
+ */
+ public TimestampServiceImpl()
+ {
+ timer = new Timer();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getNonce()
+ {
+ Long ts = getTs();
+ return String.valueOf(ts + timer.getRandomInteger());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getTimestampInSeconds()
+ {
+ return String.valueOf(getTs());
+ }
+
+ private Long getTs()
+ {
+ return timer.getMilis() / 1000;
+ }
+
+ void setTimer(Timer timer)
+ {
+ this.timer = timer;
+ }
+
+ /**
+ * Inner class that uses {@link System} for generating the timestamps.
+ *
+ * @author Pablo Fernandez
+ */
+ static class Timer
+ {
+ private final Random rand = new Random();
+ Long getMilis()
+ {
+ return System.currentTimeMillis();
+ }
+
+ Integer getRandomInteger()
+ {
+ return rand.nextInt();
+ }
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/utils/MapUtils.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/utils/MapUtils.java
new file mode 100644
index 0000000..ee09d16
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/utils/MapUtils.java
@@ -0,0 +1,24 @@
+package org.scribe.utils;
+
+import java.util.Map;
+
+/**
+ * @author: Pablo Fernandez
+ */
+public class MapUtils
+{
+ private MapUtils(){}
+
+ public static String toString(Map map)
+ {
+ if (map == null) return "";
+ if (map.isEmpty()) return "{}";
+
+ StringBuilder result = new StringBuilder();
+ for(Map.Entry entry : map.entrySet())
+ {
+ result.append(String.format(", %s -> %s ", entry.getKey().toString(), entry.getValue().toString()));
+ }
+ return "{" + result.substring(1) + "}";
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/utils/OAuthEncoder.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/utils/OAuthEncoder.java
new file mode 100644
index 0000000..7fdbc84
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/utils/OAuthEncoder.java
@@ -0,0 +1,64 @@
+package org.scribe.utils;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.regex.*;
+import org.scribe.exceptions.*;
+
+/**
+ * @author: Pablo Fernandez
+ */
+public class OAuthEncoder
+{
+ private static String CHARSET = "UTF-8";
+ private static final Map ENCODING_RULES;
+
+ static
+ {
+ Map rules = new HashMap();
+ rules.put("*", "%2A");
+ rules.put("+", "%20");
+ rules.put("%7E", "~");
+ ENCODING_RULES = Collections.unmodifiableMap(rules);
+ }
+
+ private OAuthEncoder(){}
+
+ public static String encode(String plain)
+ {
+ Preconditions.checkNotNull(plain, "Cannot encode null object");
+ String encoded = "";
+ try
+ {
+ encoded = URLEncoder.encode(plain, CHARSET);
+ }
+ catch (UnsupportedEncodingException uee)
+ {
+ throw new OAuthException("Charset not found while encoding string: " + CHARSET, uee);
+ }
+ for(Map.Entry rule : ENCODING_RULES.entrySet())
+ {
+ encoded = applyRule(encoded, rule.getKey(), rule.getValue());
+ }
+ return encoded;
+ }
+
+ private static String applyRule(String encoded, String toReplace, String replacement)
+ {
+ return encoded.replaceAll(Pattern.quote(toReplace), replacement);
+ }
+
+ public static String decode(String encoded)
+ {
+ Preconditions.checkNotNull(encoded, "Cannot decode null object");
+ try
+ {
+ return URLDecoder.decode(encoded, CHARSET);
+ }
+ catch(UnsupportedEncodingException uee)
+ {
+ throw new OAuthException("Charset not found while decoding string: " + CHARSET, uee);
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/utils/Preconditions.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/utils/Preconditions.java
new file mode 100644
index 0000000..f6e5b15
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/utils/Preconditions.java
@@ -0,0 +1,88 @@
+package org.scribe.utils;
+
+import java.util.regex.Pattern;
+
+import org.scribe.model.OAuthConstants;
+
+/**
+ * Utils for checking preconditions and invariants
+ *
+ * @author Pablo Fernandez
+ */
+public class Preconditions
+{
+ private static final String DEFAULT_MESSAGE = "Received an invalid parameter";
+
+ // scheme = alpha *( alpha | digit | "+" | "-" | "." )
+ private static final Pattern URL_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9+.-]*://\\S+");
+
+ private Preconditions(){}
+
+ /**
+ * Checks that an object is not null.
+ *
+ * @param object any object
+ * @param errorMsg error message
+ *
+ * @throws IllegalArgumentException if the object is null
+ */
+ public static void checkNotNull(Object object, String errorMsg)
+ {
+ check(object != null, errorMsg);
+ }
+
+ /**
+ * Checks that a string is not null or empty
+ *
+ * @param string any string
+ * @param errorMsg error message
+ *
+ * @throws IllegalArgumentException if the string is null or empty
+ */
+ public static void checkEmptyString(String string, String errorMsg)
+ {
+ check(string != null && !string.trim().equals(""), errorMsg);
+ }
+
+ /**
+ * Checks that a URL is valid
+ *
+ * @param url any string
+ * @param errorMsg error message
+ */
+ public static void checkValidUrl(String url, String errorMsg)
+ {
+ checkEmptyString(url, errorMsg);
+ check(isUrl(url), errorMsg);
+ }
+
+ /**
+ * Checks that a URL is a valid OAuth callback
+ *
+ * @param url any string
+ * @param errorMsg error message
+ */
+ public static void checkValidOAuthCallback(String url, String errorMsg)
+ {
+ checkEmptyString(url, errorMsg);
+ if(url.compareToIgnoreCase(OAuthConstants.OUT_OF_BAND) != 0)
+ {
+ check(isUrl(url), errorMsg);
+ }
+ }
+
+ private static boolean isUrl(String url)
+ {
+ return URL_PATTERN.matcher(url).matches();
+ }
+
+ private static void check(boolean requirements, String error)
+ {
+ String message = (error == null || error.trim().length() <= 0) ? DEFAULT_MESSAGE : error;
+ if (!requirements)
+ {
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/main/java/org/scribe/utils/StreamUtils.java b/src/main/resources/scribe-java-project/src/main/java/org/scribe/utils/StreamUtils.java
new file mode 100644
index 0000000..30dd8bc
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/main/java/org/scribe/utils/StreamUtils.java
@@ -0,0 +1,44 @@
+package org.scribe.utils;
+
+import java.io.*;
+
+/**
+ * Utils to deal with Streams.
+ *
+ * @author Pablo Fernandez
+ */
+public class StreamUtils
+{
+ private StreamUtils(){}
+
+ /**
+ * Returns the stream contents as an UTF-8 encoded string
+ *
+ * @param is input stream
+ * @return string contents
+ */
+ public static String getStreamContents(InputStream is)
+ {
+ Preconditions.checkNotNull(is, "Cannot get String from a null object");
+ try
+ {
+ final char[] buffer = new char[0x10000];
+ StringBuilder out = new StringBuilder();
+ Reader in = new InputStreamReader(is, "UTF-8");
+ int read;
+ do
+ {
+ read = in.read(buffer, 0, buffer.length);
+ if (read > 0)
+ {
+ out.append(buffer, 0, read);
+ }
+ } while (read >= 0);
+ in.close();
+ return out.toString();
+ } catch (IOException ioe)
+ {
+ throw new IllegalStateException("Error while reading response body", ioe);
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/builder/ServiceBuilderTest.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/builder/ServiceBuilderTest.java
new file mode 100644
index 0000000..8112d79
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/builder/ServiceBuilderTest.java
@@ -0,0 +1,73 @@
+package org.scribe.builder;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class ServiceBuilderTest
+{
+ private ServiceBuilder builder;
+
+ @Before
+ public void setup()
+ {
+ builder = new ServiceBuilder();
+ }
+
+ @Test
+ public void shouldReturnConfigDefaultValues()
+ {
+ builder.provider(ApiMock.class).apiKey("key").apiSecret("secret").build();
+ assertEquals(ApiMock.config.getApiKey(), "key");
+ assertEquals(ApiMock.config.getApiSecret(), "secret");
+ assertEquals(ApiMock.config.getCallback(), OAuthConstants.OUT_OF_BAND);
+ assertEquals(ApiMock.config.getSignatureType(), SignatureType.Header);
+ }
+
+ @Test
+ public void shouldAcceptValidCallbackUrl()
+ {
+ builder.provider(ApiMock.class).apiKey("key").apiSecret("secret").callback("http://example.com").build();
+ assertEquals(ApiMock.config.getApiKey(), "key");
+ assertEquals(ApiMock.config.getApiSecret(), "secret");
+ assertEquals(ApiMock.config.getCallback(), "http://example.com");
+ }
+
+ @Test
+ public void shouldAcceptASignatureType()
+ {
+ builder.provider(ApiMock.class).apiKey("key").apiSecret("secret").signatureType(SignatureType.QueryString).build();
+ assertEquals(ApiMock.config.getApiKey(), "key");
+ assertEquals(ApiMock.config.getApiSecret(), "secret");
+ assertEquals(ApiMock.config.getSignatureType(), SignatureType.QueryString);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void shouldNotAcceptNullAsCallback()
+ {
+ builder.provider(ApiMock.class).apiKey("key").apiSecret("secret").callback(null).build();
+ }
+
+ @Test
+ public void shouldAcceptAnScope()
+ {
+ builder.provider(ApiMock.class).apiKey("key").apiSecret("secret").scope("rss-api").build();
+ assertEquals(ApiMock.config.getApiKey(), "key");
+ assertEquals(ApiMock.config.getApiSecret(), "secret");
+ assertEquals(ApiMock.config.getScope(), "rss-api");
+ }
+
+ public static class ApiMock implements Api
+ {
+ public static OAuthConfig config;
+
+ public OAuthService createService(OAuthConfig config)
+ {
+ ApiMock.config = config;
+ return null;
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/AWeberExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/AWeberExample.java
new file mode 100644
index 0000000..2d86d61
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/AWeberExample.java
@@ -0,0 +1,65 @@
+package org.scribe.examples;
+
+import java.util.Scanner;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class AWeberExample
+{
+
+ //To get your consumer key/secret, and view API docs, see https://labs.aweber.com/docs
+ private static final String ACCOUNT_RESOURCE_URL = "https://api.aweber.com/1.0/accounts/";
+
+ private static final String CONSUMER_KEY = "";
+ private static final String CONSUMER_SECRET = "";
+
+ public static void main(String[] args)
+ {
+ OAuthService service = new ServiceBuilder()
+ .provider(AWeberApi.class)
+ .apiKey(CONSUMER_KEY)
+ .apiSecret(CONSUMER_SECRET)
+ .build();
+
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== AWeber's OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Request Token
+ System.out.println("Fetching the Request Token...");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got the Request Token!");
+ System.out.println();
+
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(service.getAuthorizationUrl(requestToken));
+ System.out.println("And paste the verifier here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, ACCOUNT_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with AWeber and Scribe! :)");
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/DiggExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/DiggExample.java
new file mode 100644
index 0000000..63fea8b
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/DiggExample.java
@@ -0,0 +1,65 @@
+package org.scribe.examples;
+
+import java.util.*;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class DiggExample
+{
+ private static final String NETWORK_NAME = "Digg";
+ private static final String PROTECTED_RESOURCE_URL = "http://services.digg.com/2.0/comment.digg";
+
+ public static void main(String[] args)
+ {
+ // Replace these with your own api key and secret
+ String apiKey = "myKey";
+ String apiSecret = "mySecret";
+ OAuthService service = new ServiceBuilder().provider(DiggApi.class).apiKey(apiKey).apiSecret(apiSecret).build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Request Token
+ System.out.println("Fetching the Request Token...");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got the Request Token!");
+ System.out.println();
+
+ // Obtain the Authorization URL
+ System.out.println("Fetching the Authorization URL...");
+ String authorizationUrl = service.getAuthorizationUrl(requestToken);
+ System.out.println("Got the Authorization URL!");
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(authorizationUrl);
+ System.out.println("And paste the authorization code here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.POST, PROTECTED_RESOURCE_URL);
+ request.addBodyParameter("comment_id", "20100729223726:4fef610331ee46a3b5cbd740bf71313e");
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/FacebookExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/FacebookExample.java
new file mode 100644
index 0000000..d5dc3cb
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/FacebookExample.java
@@ -0,0 +1,64 @@
+package org.scribe.examples;
+
+import java.util.*;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class FacebookExample
+{
+ private static final String NETWORK_NAME = "Facebook";
+ private static final String PROTECTED_RESOURCE_URL = "https://graph.facebook.com/me";
+ private static final Token EMPTY_TOKEN = null;
+
+ public static void main(String[] args)
+ {
+ // Replace these with your own api key and secret
+ String apiKey = "your_app_id";
+ String apiSecret = "your_api_secret";
+ OAuthService service = new ServiceBuilder()
+ .provider(FacebookApi.class)
+ .apiKey(apiKey)
+ .apiSecret(apiSecret)
+ .callback("http://www.example.com/oauth_callback/")
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Authorization URL
+ System.out.println("Fetching the Authorization URL...");
+ String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN);
+ System.out.println("Got the Authorization URL!");
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(authorizationUrl);
+ System.out.println("And paste the authorization code here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/FlickrExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/FlickrExample.java
new file mode 100644
index 0000000..ac38ad3
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/FlickrExample.java
@@ -0,0 +1,59 @@
+package org.scribe.examples;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+import java.util.*;
+
+public class FlickrExample
+{
+ private static final String PROTECTED_RESOURCE_URL = "http://api.flickr.com/services/rest/";
+
+ public static void main(String[] args)
+ {
+ // Replace these with your own api key and secret
+ String apiKey = "your_app_id";
+ String apiSecret = "your_api_secret";
+ OAuthService service = new ServiceBuilder().provider(FlickrApi.class).apiKey(apiKey).apiSecret(apiSecret).build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== Flickr's OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Request Token
+ System.out.println("Fetching the Request Token...");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got the Request Token!");
+ System.out.println();
+
+ System.out.println("Now go and authorize Scribe here:");
+ String authorizationUrl = service.getAuthorizationUrl(requestToken);
+ System.out.println(authorizationUrl + "&perms=read");
+ System.out.println("And paste the verifier here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ request.addQuerystringParameter("method", "flickr.test.login");
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/Foursquare2Example.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/Foursquare2Example.java
new file mode 100644
index 0000000..35495a8
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/Foursquare2Example.java
@@ -0,0 +1,63 @@
+package org.scribe.examples;
+
+import java.util.*;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class Foursquare2Example
+{
+ private static final String PROTECTED_RESOURCE_URL = "https://api.foursquare.com/v2/users/self/friends?oauth_token=";
+ private static final Token EMPTY_TOKEN = null;
+
+ public static void main(String[] args)
+ {
+ // Replace these with your own api key and secret
+ String apiKey = "FEGFXJUFANVVDHVSNUAMUKTTXCP1AJQD53E33XKJ44YP1S4I";
+ String apiSecret = "AYWKUL5SWPNC0CTQ202QXRUG2NLZYXMRA34ZSDW4AUYBG2RC";
+ OAuthService service = new ServiceBuilder()
+ .provider(Foursquare2Api.class)
+ .apiKey(apiKey)
+ .apiSecret(apiSecret)
+ .callback("http://localhost:9000/")
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== Foursquare2's OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Authorization URL
+ System.out.println("Fetching the Authorization URL...");
+ String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN);
+ System.out.println("Got the Authorization URL!");
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(authorizationUrl);
+ System.out.println("And paste the authorization code here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL + accessToken.getToken());
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/FoursquareExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/FoursquareExample.java
new file mode 100644
index 0000000..b227488
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/FoursquareExample.java
@@ -0,0 +1,59 @@
+package org.scribe.examples;
+
+import java.util.Scanner;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class FoursquareExample
+{
+ private static final String PROTECTED_RESOURCE_URL = "http://api.foursquare.com/v1/user";
+
+ public static void main(String[] args)
+ {
+ OAuthService service = new ServiceBuilder()
+ .provider(FoursquareApi.class)
+ .apiKey("FEGFXJUFANVVDHVSNUAMUKTTXCP1AJQD53E33XKJ44YP1S4I")
+ .apiSecret("AYWKUL5SWPNC0CTQ202QXRUG2NLZYXMRA34ZSDW4AUYBG2RC")
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== Foursquare's OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Request Token
+ System.out.println("Fetching the Request Token...");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got the Request Token!");
+ System.out.println();
+
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(service.getAuthorizationUrl(requestToken));
+ System.out.println("And paste the verifier here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/FreelancerExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/FreelancerExample.java
new file mode 100644
index 0000000..d1d5407
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/FreelancerExample.java
@@ -0,0 +1,66 @@
+package org.scribe.examples;
+
+import java.util.*;
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class FreelancerExample
+{
+
+ private static final String NETWORK_NAME = "Freelancer";
+ private static final String AUTHORIZE_URL = "http://www.sandbox.freelancer.com/users/api-token/auth.php?oauth_token=";
+ private static final String PROTECTED_RESOURCE_URL = "http://api.sandbox.freelancer.com/Job/getJobList.json";
+ private static final String SCOPE = "http://api.sandbox.freelancer.com";
+
+ public static void main(String[] args)
+ {
+ OAuthService service = new ServiceBuilder()
+ .provider(FreelancerApi.Sandbox.class)
+ .signatureType(SignatureType.QueryString)
+ .apiKey("7f5a168a0bfdbd15b4a9ea2a969661c731cdea56")
+ .apiSecret("7bb8961b94873802f1c5344f671a518e087f5785")
+ .scope(SCOPE)
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Request Token
+ System.out.println("Fetching the Request Token...");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got the Request Token!");
+ System.out.println("(if your curious it looks like this: " + requestToken + " )");
+ System.out.println();
+
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(AUTHORIZE_URL + requestToken.getToken());
+ System.out.println("And paste the verifier here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ request.addHeader("GData-Version", "3.0");
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/GoogleExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/GoogleExample.java
new file mode 100644
index 0000000..fef1b43
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/GoogleExample.java
@@ -0,0 +1,66 @@
+package org.scribe.examples;
+
+import java.util.*;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class GoogleExample
+{
+ private static final String NETWORK_NAME = "Google";
+ private static final String AUTHORIZE_URL = "https://www.google.com/accounts/OAuthAuthorizeToken?oauth_token=";
+ private static final String PROTECTED_RESOURCE_URL = "https://docs.google.com/feeds/default/private/full/";
+ private static final String SCOPE = "https://docs.google.com/feeds/";
+
+ public static void main(String[] args)
+ {
+ OAuthService service = new ServiceBuilder()
+ .provider(GoogleApi.class)
+ .apiKey("anonymous")
+ .apiSecret("anonymous")
+ .scope(SCOPE)
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Request Token
+ System.out.println("Fetching the Request Token...");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got the Request Token!");
+ System.out.println("(if your curious it looks like this: " + requestToken + " )");
+ System.out.println();
+
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(AUTHORIZE_URL + requestToken.getToken());
+ System.out.println("And paste the verifier here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ request.addHeader("GData-Version", "3.0");
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/ImgUrExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/ImgUrExample.java
new file mode 100644
index 0000000..93fe91c
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/ImgUrExample.java
@@ -0,0 +1,58 @@
+package org.scribe.examples;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+import java.util.*;
+
+public class ImgUrExample
+{
+ private static final String PROTECTED_RESOURCE_URL = "http://api.imgur.com/2/account.json";
+
+ public static void main(String[] args)
+ {
+ // Replace these with your own api key and secret (you'll need an read/write api key)
+ String apiKey = "your_app_id";
+ String apiSecret = "your_api_secret";
+ OAuthService service = new ServiceBuilder().provider(ImgUrApi.class).apiKey(apiKey).apiSecret(apiSecret).build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== ImgUr's OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Request Token
+ System.out.println("Fetching the Request Token...");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got the Request Token!");
+ System.out.println();
+
+ System.out.println("Now go and authorize Scribe here:");
+ String authorizationUrl = service.getAuthorizationUrl(requestToken);
+ System.out.println(authorizationUrl);
+ System.out.println("And paste the verifier here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/Kaixin20Example.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/Kaixin20Example.java
new file mode 100644
index 0000000..b3e9d66
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/Kaixin20Example.java
@@ -0,0 +1,63 @@
+package org.scribe.examples;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+import java.util.*;
+
+public class Kaixin20Example
+{
+ private static final String NETWORK_NAME = "Kaixin";
+ private static final String PROTECTED_RESOURCE_URL = "https://api.kaixin001.com/users/me.json";
+ private static final Token EMPTY_TOKEN = null;
+
+ public static void main(String[] args)
+ {
+ // Replace these with your own api key and secret
+ String apiKey = "your api key";
+ String apiSecret = "your api secret";
+ OAuthService service = new ServiceBuilder()
+ .provider(KaixinApi20.class)
+ .apiKey(apiKey)
+ .apiSecret(apiSecret)
+ .callback("http://your.domain.com/handle")
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Authorization URL
+ System.out.println("Fetching the Authorization URL...");
+ String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN);
+ System.out.println("Got the Authorization URL!");
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(authorizationUrl);
+ System.out.println("And paste the authorization code here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verifier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/LinkedInExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/LinkedInExample.java
new file mode 100644
index 0000000..703cc82
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/LinkedInExample.java
@@ -0,0 +1,59 @@
+package org.scribe.examples;
+
+import java.util.Scanner;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class LinkedInExample
+{
+ private static final String PROTECTED_RESOURCE_URL = "http://api.linkedin.com/v1/people/~/connections:(id,last-name)";
+
+ public static void main(String[] args)
+ {
+ OAuthService service = new ServiceBuilder()
+ .provider(LinkedInApi.class)
+ .apiKey("CiEgwWDkA5BFpNrc0RfGyVuSlOh4tig5kOTZ9q97qcXNrFl7zqk-Ts7DqRGaKDCV")
+ .apiSecret("dhho4dfoCmiQXrkw4yslork5XWLFnPSuMR-8gscPVjY4jqFFHPYWJKgpFl4uLTM6")
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== LinkedIn's OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Request Token
+ System.out.println("Fetching the Request Token...");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got the Request Token!");
+ System.out.println();
+
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(service.getAuthorizationUrl(requestToken));
+ System.out.println("And paste the verifier here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/LinkedInExampleWithScopes.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/LinkedInExampleWithScopes.java
new file mode 100644
index 0000000..b8e8b28
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/LinkedInExampleWithScopes.java
@@ -0,0 +1,59 @@
+package org.scribe.examples;
+
+import java.util.Scanner;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class LinkedInExampleWithScopes
+{
+ private static final String PROTECTED_RESOURCE_URL = "http://api.linkedin.com/v1/people/~/connections:(id,last-name)";
+
+ public static void main(String[] args)
+ {
+ OAuthService service = new ServiceBuilder()
+ .provider(LinkedInApi.withScopes("foo", "bar", "baz"))
+ .apiKey("CiEgwWDkA5BFpNrc0RfGyVuSlOh4tig5kOTZ9q97qcXNrFl7zqk-Ts7DqRGaKDCV")
+ .apiSecret("dhho4dfoCmiQXrkw4yslork5XWLFnPSuMR-8gscPVjY4jqFFHPYWJKgpFl4uLTM6")
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== LinkedIn's OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Request Token
+ System.out.println("Fetching the Request Token...");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got the Request Token!");
+ System.out.println();
+
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(service.getAuthorizationUrl(requestToken));
+ System.out.println("And paste the verifier here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/LiveExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/LiveExample.java
new file mode 100644
index 0000000..ade5a6b
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/LiveExample.java
@@ -0,0 +1,64 @@
+package org.scribe.examples;
+
+import java.util.*;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class LiveExample
+{
+ private static final String PROTECTED_RESOURCE_URL = "https://api.foursquare.com/v2/users/self/friends?oauth_token=";
+ private static final Token EMPTY_TOKEN = null;
+
+ public static void main(String[] args)
+ {
+ // Replace these with your own api key and secret
+ String apiKey = "";
+ String apiSecret = "";
+ OAuthService service = new ServiceBuilder()
+ .provider(LiveApi.class)
+ .apiKey(apiKey)
+ .apiSecret(apiSecret)
+ .scope("wl.basic")
+ .callback("http://localhost:9000/")
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== Windows Live's OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Authorization URL
+ System.out.println("Fetching the Authorization URL...");
+ String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN);
+ System.out.println("Got the Authorization URL!");
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(authorizationUrl);
+ System.out.println("And paste the authorization code here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL + accessToken.getToken());
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/LoveFilmExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/LoveFilmExample.java
new file mode 100644
index 0000000..9e80016
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/LoveFilmExample.java
@@ -0,0 +1,64 @@
+package org.scribe.examples;
+
+import java.util.*;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class LoveFilmExample
+{
+ private static final String NETWORK_NAME = "LoveFilm";
+ private static final String PROTECTED_RESOURCE_URL = "https://api.lovefilm.com/users";
+
+ public static void main(String[] args)
+ {
+ // Replace these with your own api key and secret
+ String apiKey = "your_key";
+ String apiSecret = "your_secret";
+ OAuthService service = new ServiceBuilder().provider(LoveFilmApi.class).apiKey(apiKey).apiSecret(apiSecret).build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
+ System.out.println();
+
+ // Grab a request token.
+ System.out.println("Fetching request token.");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got it ... ");
+ System.out.println(requestToken.getToken());
+
+ // Obtain the Authorization URL
+ System.out.println("Fetching the Authorization URL...");
+ String authorizationUrl = service.getAuthorizationUrl(requestToken);
+ System.out.println("Got the Authorization URL!");
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(authorizationUrl);
+ System.out.println("And paste the authorization code here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/MeetupExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/MeetupExample.java
new file mode 100644
index 0000000..2185b5c
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/MeetupExample.java
@@ -0,0 +1,62 @@
+package org.scribe.examples;
+
+import java.util.Scanner;
+
+import org.scribe.builder.ServiceBuilder;
+import org.scribe.builder.api.MeetupApi;
+import org.scribe.model.OAuthRequest;
+import org.scribe.model.Response;
+import org.scribe.model.Token;
+import org.scribe.model.Verb;
+import org.scribe.model.Verifier;
+import org.scribe.oauth.OAuthService;
+
+public class MeetupExample
+{
+ private static final String PROTECTED_RESOURCE_URL = "http://api.meetup.com/2/member/self";
+
+ public static void main(String[] args)
+ {
+ OAuthService service = new ServiceBuilder()
+ .provider(MeetupApi.class)
+ .apiKey("j1khkp0dus323ftve0sdcv6ffe")
+ .apiSecret("6s6gt6q59gvfjtsvgcmht62gq4")
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== Meetup's OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Request Token
+ System.out.println("Fetching the Request Token...");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got the Request Token!");
+ System.out.println();
+
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(service.getAuthorizationUrl(requestToken));
+ System.out.println("And paste the verifier here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/NeteaseWeiboExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/NeteaseWeiboExample.java
new file mode 100644
index 0000000..e65335e
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/NeteaseWeiboExample.java
@@ -0,0 +1,68 @@
+package org.scribe.examples;
+
+import java.util.*;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class NeteaseWeiboExample
+{
+ private static final String NETWORK_NAME = "NetEase(163.com) Weibo";
+ private static final String PROTECTED_RESOURCE_URL = "http://api.t.163.com/account/verify_credentials.json";
+
+ public static void main(String[] args)
+ {
+ // Replace these with your own api key and secret
+ String apiKey = "your key";
+ String apiSecret = "your secret";
+ OAuthService service = new ServiceBuilder()
+ .provider(NeteaseWeibooApi.class)
+ .apiKey(apiKey)
+ .apiSecret(apiSecret)
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
+ System.out.println();
+
+ // Grab a request token.
+ System.out.println("Fetching request token.");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got it ... ");
+ System.out.println(requestToken.getToken());
+
+ // Obtain the Authorization URL
+ System.out.println("Fetching the Authorization URL...");
+ String authorizationUrl = service.getAuthorizationUrl(requestToken);
+ System.out.println("Got the Authorization URL!");
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(authorizationUrl);
+ System.out.println("And paste the authorization code here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: "
+ + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/Px500Example.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/Px500Example.java
new file mode 100644
index 0000000..cdbe449
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/Px500Example.java
@@ -0,0 +1,60 @@
+package org.scribe.examples;
+
+import java.util.Scanner;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class Px500Example
+{
+ private static final String PROTECTED_RESOURCE_URL = "https://api.500px.com/v1/";
+
+ public static void main(String[] args)
+ {
+ OAuthService service = new ServiceBuilder()
+ .provider(Px500Api.class)
+ .apiKey("your-api-key")
+ .apiSecret("your-api-secret")
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== 500Px's OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Request Token
+ System.out.println("Fetching the Request Token...");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got the Request Token!");
+ System.out.println();
+
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(service.getAuthorizationUrl(requestToken));
+ System.out.println("And paste the verifier here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/RenrenExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/RenrenExample.java
new file mode 100644
index 0000000..ae13375
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/RenrenExample.java
@@ -0,0 +1,108 @@
+package org.scribe.examples;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+import java.nio.charset.*;
+import java.security.*;
+import java.util.*;
+
+public class RenrenExample
+{
+ private static final String NETWORK_NAME = "Renren";
+ private static final String PROTECTED_RESOURCE_URL = "http://api.renren.com/restserver.do";
+ private static final Token EMPTY_TOKEN = null;
+
+ public static void main(String[] args)
+ {
+ // Replace these with your own api key and secret
+ String apiKey = "your api key";
+ String apiSecret = "your api secret";
+ OAuthService service = new ServiceBuilder()
+ .provider(RenrenApi.class)
+ .apiKey(apiKey)
+ .apiSecret(apiSecret)
+ .scope("status_update publish_feed")
+ .callback("http://your.doman.com/oauth/renren")
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Authorization URL
+ System.out.println("Fetching the Authorization URL...");
+ String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN);
+ System.out.println("Got the Authorization URL!");
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(authorizationUrl);
+ System.out.println("And paste the authorization code here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.POST, PROTECTED_RESOURCE_URL);
+ Map parameters = new HashMap();
+ parameters.put("method", "users.getInfo");
+ parameters.put("format", "json");
+ parameters.put("v", "1.0");
+
+ List sigString = new ArrayList(parameters.size() + 1);
+ for (Map.Entry entry : parameters.entrySet())
+ {
+ request.addQuerystringParameter(entry.getKey(), entry.getValue());
+ sigString.add(String.format("%s=%s", entry.getKey(), entry.getValue()));
+ }
+ sigString.add(String.format("%s=%s", OAuthConstants.ACCESS_TOKEN, accessToken.getToken()));
+ Collections.sort(sigString);
+ StringBuilder b = new StringBuilder();
+ for (String param : sigString)
+ {
+ b.append(param);
+ }
+ b.append(apiSecret);
+ System.out.println("Sig string: " + b.toString());
+ request.addQuerystringParameter("sig", md5(b.toString()));
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+
+ }
+
+ public static String md5(String orgString)
+ {
+ try
+ {
+ java.security.MessageDigest md = MessageDigest.getInstance("MD5");
+ byte[] array = md.digest(orgString.getBytes(Charset.forName("UTF-8")));
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < array.length; ++i)
+ {
+ sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1, 3));
+ }
+ return sb.toString();
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/SinaWeibo2Example.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/SinaWeibo2Example.java
new file mode 100644
index 0000000..89b14e1
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/SinaWeibo2Example.java
@@ -0,0 +1,63 @@
+package org.scribe.examples;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+import java.util.*;
+
+public class SinaWeibo2Example
+{
+ private static final String NETWORK_NAME = "SinaWeibo";
+ private static final String PROTECTED_RESOURCE_URL = "https://api.weibo.com/2/account/get_uid.json";
+ private static final Token EMPTY_TOKEN = null;
+
+ public static void main(String[] args)
+ {
+ // Replace these with your own api key and secret
+ String apiKey = "your_api_key";
+ String apiSecret = "your_api_secret";
+ OAuthService service = new ServiceBuilder()
+ .provider(SinaWeiboApi20.class)
+ .apiKey(apiKey)
+ .apiSecret(apiSecret)
+ .callback("http://www.dajie.com/oauth/sina")
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Authorization URL
+ System.out.println("Fetching the Authorization URL...");
+ String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN);
+ System.out.println("Got the Authorization URL!");
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(authorizationUrl);
+ System.out.println("And paste the authorization code here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verifier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/SinaWeiboExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/SinaWeiboExample.java
new file mode 100644
index 0000000..2dc4b7c
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/SinaWeiboExample.java
@@ -0,0 +1,68 @@
+package org.scribe.examples;
+
+import java.util.*;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class SinaWeiboExample
+{
+ private static final String NETWORK_NAME = "SinaWeibo";
+ private static final String PROTECTED_RESOURCE_URL = "http://api.t.sina.com.cn/account/verify_credentials.json";
+
+ public static void main(String[] args)
+ {
+ // Replace these with your own api key and secret
+ String apiKey = "your key";
+ String apiSecret = "your secret";
+ OAuthService service = new ServiceBuilder()
+ .provider(SinaWeiboApi.class)
+ .apiKey(apiKey)
+ .apiSecret(apiSecret)
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
+ System.out.println();
+
+ // Grab a request token.
+ System.out.println("Fetching request token.");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got it ... ");
+ System.out.println(requestToken.getToken());
+
+ // Obtain the Authorization URL
+ System.out.println("Fetching the Authorization URL...");
+ String authorizationUrl = service.getAuthorizationUrl(requestToken);
+ System.out.println("Got the Authorization URL!");
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(authorizationUrl);
+ System.out.println("And paste the authorization code here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: "
+ + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/SkyrockExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/SkyrockExample.java
new file mode 100644
index 0000000..422d067
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/SkyrockExample.java
@@ -0,0 +1,61 @@
+package org.scribe.examples;
+
+import java.util.Scanner;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class SkyrockExample
+{
+ private static final String PROTECTED_RESOURCE_URL = "https://api.skyrock.com/v2/user/get.json";
+
+ public static void main(String[] args)
+ {
+ OAuthService service = new ServiceBuilder()
+ .provider(SkyrockApi.class)
+ .apiKey("your-api-key")
+ .apiSecret("your-api-secret")
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== Skyrock's OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Request Token
+ System.out.println("Fetching the Request Token...");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got the Request Token!");
+ System.out.println();
+
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(service.getAuthorizationUrl(requestToken));
+ System.out.println("And paste the verifier here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/SohuWeiboExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/SohuWeiboExample.java
new file mode 100644
index 0000000..49dd9fb
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/SohuWeiboExample.java
@@ -0,0 +1,68 @@
+package org.scribe.examples;
+
+import java.util.*;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class SohuWeiboExample
+{
+ private static final String NETWORK_NAME = "SohuWeibo";
+ private static final String PROTECTED_RESOURCE_URL = "http://api.t.sohu.com/account/verify_credentials.json";
+
+ public static void main(String[] args)
+ {
+ // Replace these with your own api key and secret
+ String apiKey = "your_key";
+ String apiSecret = "your_secret";
+ OAuthService service = new ServiceBuilder()
+ .provider(SohuWeiboApi.class)
+ .apiKey(apiKey)
+ .apiSecret(apiSecret)
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
+ System.out.println();
+
+ // Grab a request token.
+ System.out.println("Fetching request token.");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got it ... ");
+ System.out.println(requestToken.getToken());
+
+ // Obtain the Authorization URL
+ System.out.println("Fetching the Authorization URL...");
+ String authorizationUrl = service.getAuthorizationUrl(requestToken);
+ System.out.println("Got the Authorization URL!");
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(authorizationUrl);
+ System.out.println("And paste the authorization code here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: "
+ + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/TrelloExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/TrelloExample.java
new file mode 100644
index 0000000..9888f5e
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/TrelloExample.java
@@ -0,0 +1,60 @@
+package org.scribe.examples;
+
+import java.util.Scanner;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class TrelloExample
+{
+ private static final String API_KEY = "your_api_key";
+ private static final String API_SECRET = "your_api_secret";
+ private static final String PROTECTED_RESOURCE_URL = "https://trello.com/1/members/me";
+ public static void main(String[] args)
+ {
+ OAuthService service = new ServiceBuilder()
+ .provider(TrelloApi.class)
+ .apiKey(API_KEY)
+ .apiSecret(API_SECRET)
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== Trello's OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Request Token
+ System.out.println("Fetching the Request Token...");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got the Request Token!");
+ System.out.println();
+
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(service.getAuthorizationUrl(requestToken));
+ System.out.println("And paste the verifier here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/TumblrExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/TumblrExample.java
new file mode 100644
index 0000000..d024efb
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/TumblrExample.java
@@ -0,0 +1,62 @@
+package org.scribe.examples;
+
+import java.util.Scanner;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class TumblrExample
+{
+ private static final String PROTECTED_RESOURCE_URL = "http://api.tumblr.com/v2/user/info";
+
+ public static void main( String[] args )
+ {
+ OAuthService service = new ServiceBuilder()
+ .provider( TumblrApi.class )
+ .apiKey( "MY_CONSUMER_KEY" )
+ .apiSecret( "MY_CONSUMER_SECRET" )
+ .callback( "http://www.tumblr.com/connect/login_success.html" ) // OOB forbidden. We need an url and the better is on the tumblr website !
+ .build();
+ Scanner in = new Scanner( System.in );
+
+ System.out.println( "=== Tumblr's OAuth Workflow ===" );
+ System.out.println();
+
+ // Obtain the Request Token
+ System.out.println( "Fetching the Request Token..." );
+ Token requestToken = service.getRequestToken();
+ System.out.println( "Got the Request Token!" );
+ System.out.println();
+
+ System.out.println( "Now go and authorize Scribe here:" );
+ System.out.println( service.getAuthorizationUrl( requestToken ) );
+ System.out.println( "And paste the verifier here" );
+ System.out.print( ">>" );
+ Verifier verifier = new Verifier( in.nextLine() );
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println( "Trading the Request Token for an Access Token..." );
+ Token accessToken = service.getAccessToken( requestToken ,
+ verifier );
+ System.out.println( "Got the Access Token!" );
+ System.out.println( "(if your curious it looks like this: " + accessToken + " )" );
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println( "Now we're going to access a protected resource..." );
+ OAuthRequest request = new OAuthRequest( Verb.GET ,
+ PROTECTED_RESOURCE_URL );
+ service.signRequest( accessToken ,
+ request );
+ Response response = request.send();
+ System.out.println( "Got it! Lets see what we found..." );
+ System.out.println();
+ System.out.println( response.getBody() );
+
+ System.out.println();
+ System.out.println( "Thats it man! Go and build something awesome with Scribe! :)" );
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/TwitterExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/TwitterExample.java
new file mode 100644
index 0000000..4f3435b
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/TwitterExample.java
@@ -0,0 +1,61 @@
+package org.scribe.examples;
+
+import java.util.Scanner;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class TwitterExample
+{
+ private static final String PROTECTED_RESOURCE_URL = "https://api.twitter.com/1.1/account/verify_credentials.json";
+
+ public static void main(String[] args)
+ {
+ // If you choose to use a callback, "oauth_verifier" will be the return value by Twitter (request param)
+ OAuthService service = new ServiceBuilder()
+ .provider(TwitterApi.class)
+ .apiKey("6icbcAXyZx67r8uTAUM5Qw")
+ .apiSecret("SCCAdUUc6LXxiazxH3N0QfpNUvlUy84mZ2XZKiv39s")
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== Twitter's OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Request Token
+ System.out.println("Fetching the Request Token...");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got the Request Token!");
+ System.out.println();
+
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(service.getAuthorizationUrl(requestToken));
+ System.out.println("And paste the verifier here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ request.addBodyParameter("status", "this is sparta! *");
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/ViadeoExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/ViadeoExample.java
new file mode 100644
index 0000000..ebb4385
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/ViadeoExample.java
@@ -0,0 +1,64 @@
+package org.scribe.examples;
+
+import java.util.*;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class ViadeoExample
+{
+ private static final String NETWORK_NAME = "Viadeo";
+ private static final String PROTECTED_RESOURCE_URL = "https://api.viadeo.com/me?user_detail=full";
+ private static final Token EMPTY_TOKEN = null;
+
+ public static void main(String[] args)
+ {
+ // Replace these with your own api key and secret
+ String apiKey = "your_app_id";
+ String apiSecret = "your_api_secret";
+ OAuthService service = new ServiceBuilder()
+ .provider(ViadeoApi.class)
+ .apiKey(apiKey)
+ .apiSecret(apiSecret)
+ .callback("http://www.example.com/oauth_callback/")
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Authorization URL
+ System.out.println("Fetching the Authorization URL...");
+ String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN);
+ System.out.println("Got the Authorization URL!");
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(authorizationUrl);
+ System.out.println("And paste the authorization code here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/VkontakteExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/VkontakteExample.java
new file mode 100644
index 0000000..f9e4134
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/VkontakteExample.java
@@ -0,0 +1,68 @@
+package org.scribe.examples;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+import java.util.*;
+
+/**
+ * @author Boris G. Tsirkin
+ * @since 20.4.2011
+ */
+public class VkontakteExample
+{
+ private static final String NETWORK_NAME = "Vkontakte.ru";
+ private static final String PROTECTED_RESOURCE_URL = "https://api.vkontakte.ru/method/friends.get";
+ private static final Token EMPTY_TOKEN = null;
+
+ public static void main(String[] args)
+ {
+ // Replace these with your own api key and secret
+ final String clientId = "your app id";
+ final String apiSecret = "your api secret";
+ OAuthService service = new ServiceBuilder()
+ .provider(VkontakteApi.class)
+ .apiKey(clientId)
+ .apiSecret(apiSecret)
+ .scope("friends,wall,offline") // replace with desired scope
+ .callback("http://your.site.com/callback")
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Authorization URL
+ System.out.println("Fetching the Authorization URL...");
+ String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN);
+ System.out.println("Got the Authorization URL!");
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(authorizationUrl);
+ System.out.println("And paste the authorization code here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/XingExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/XingExample.java
new file mode 100755
index 0000000..93d7080
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/XingExample.java
@@ -0,0 +1,59 @@
+package org.scribe.examples;
+
+import java.util.Scanner;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class XingExample
+{
+ private static final String PROTECTED_RESOURCE_URL = "https://api.xing.com/v1/users/me";
+
+ public static void main(String[] args)
+ {
+ OAuthService service = new ServiceBuilder()
+ .provider(XingApi.class)
+ .apiKey("097ccfd3ef25a1cb6d75")
+ .apiSecret("e43364b2afd5d92f2ec28951a75bd8075f9cc221")
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== Xing's OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Request Token
+ System.out.println("Fetching the Request Token...");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got the Request Token!");
+ System.out.println();
+
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(service.getAuthorizationUrl(requestToken));
+ System.out.println("And paste the verifier here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/YahooExample.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/YahooExample.java
new file mode 100644
index 0000000..2e3f336
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/examples/YahooExample.java
@@ -0,0 +1,60 @@
+package org.scribe.examples;
+
+import java.util.Scanner;
+
+import org.scribe.builder.*;
+import org.scribe.builder.api.*;
+import org.scribe.model.*;
+import org.scribe.oauth.*;
+
+public class YahooExample
+{
+ private static final String PROTECTED_RESOURCE_URL = "http://social.yahooapis.com/v1/user/A6ROU63MXWDCW3Y5MGCYWVHDJI/profile/status?format=json";
+
+ public static void main(String[] args)
+ {
+ OAuthService service = new ServiceBuilder()
+ .provider(YahooApi.class)
+ .apiKey("dj0yJmk9TXZDWVpNVVdGaVFmJmQ9WVdrOWMweHZXbkZLTkhVbWNHbzlNVEl5TWprd05qUTJNZy0tJnM9Y29uc3VtZXJzZWNyZXQmeD0wMw--")
+ .apiSecret("262be559f92a2be20c4c039419018f2b48cdfce9")
+ .build();
+ Scanner in = new Scanner(System.in);
+
+ System.out.println("=== Yahoo's OAuth Workflow ===");
+ System.out.println();
+
+ // Obtain the Request Token
+ System.out.println("Fetching the Request Token...");
+ Token requestToken = service.getRequestToken();
+ System.out.println("Got the Request Token!");
+ System.out.println();
+
+ System.out.println("Now go and authorize Scribe here:");
+ System.out.println(service.getAuthorizationUrl(requestToken));
+ System.out.println("And paste the verifier here");
+ System.out.print(">>");
+ Verifier verifier = new Verifier(in.nextLine());
+ System.out.println();
+
+ // Trade the Request Token and Verfier for the Access Token
+ System.out.println("Trading the Request Token for an Access Token...");
+ Token accessToken = service.getAccessToken(requestToken, verifier);
+ System.out.println("Got the Access Token!");
+ System.out.println("(if your curious it looks like this: " + accessToken + " )");
+ System.out.println();
+
+ // Now let's go and ask for a protected resource!
+ System.out.println("Now we're going to access a protected resource...");
+ OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
+ service.signRequest(accessToken, request);
+ Response response = request.send();
+ System.out.println("Got it! Lets see what we found...");
+ System.out.println();
+ System.out.println(response.getCode());
+ System.out.println(response.getBody());
+
+ System.out.println();
+ System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
+
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/extractors/BaseStringExtractorTest.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/extractors/BaseStringExtractorTest.java
new file mode 100644
index 0000000..0fac082
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/extractors/BaseStringExtractorTest.java
@@ -0,0 +1,102 @@
+package org.scribe.extractors;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.scribe.exceptions.*;
+import org.scribe.model.*;
+import org.scribe.test.helpers.*;
+
+public class BaseStringExtractorTest
+{
+
+ private BaseStringExtractorImpl extractor;
+ private OAuthRequest request;
+ private OAuthRequest requestPort80;
+ private OAuthRequest requestPort80_2;
+ private OAuthRequest requestPort8080;
+ private OAuthRequest requestPort443;
+ private OAuthRequest requestPort443_2;
+
+ @Before
+ public void setup()
+ {
+ request = ObjectMother.createSampleOAuthRequest();
+ requestPort80 = ObjectMother.createSampleOAuthRequestPort80();
+ requestPort80_2 = ObjectMother.createSampleOAuthRequestPort80_2();
+ requestPort8080 = ObjectMother.createSampleOAuthRequestPort8080();
+ requestPort443 = ObjectMother.createSampleOAuthRequestPort443();
+ requestPort443_2 = ObjectMother.createSampleOAuthRequestPort443_2();
+ extractor = new BaseStringExtractorImpl();
+ }
+
+ @Test
+ public void shouldExtractBaseStringFromOAuthRequest()
+ {
+ String expected = "GET&http%3A%2F%2Fexample.com&oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature%3DOAuth-Signature%26oauth_timestamp%3D123456";
+ String baseString = extractor.extract(request);
+ assertEquals(expected, baseString);
+ }
+
+ @Test
+ public void shouldExcludePort80()
+ {
+ String expected = "GET&http%3A%2F%2Fexample.com&oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature%3DOAuth-Signature%26oauth_timestamp%3D123456";
+ String baseString = extractor.extract(requestPort80);
+ assertEquals(expected, baseString);
+ }
+
+ @Test
+ public void shouldExcludePort80_2()
+ {
+ String expected = "GET&http%3A%2F%2Fexample.com%2Ftest&oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature%3DOAuth-Signature%26oauth_timestamp%3D123456";
+ String baseString = extractor.extract(requestPort80_2);
+ assertEquals(expected, baseString);
+ }
+
+ @Test
+ public void shouldIncludePort8080()
+ {
+ String expected = "GET&http%3A%2F%2Fexample.com%3A8080&oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature%3DOAuth-Signature%26oauth_timestamp%3D123456";
+ String baseString = extractor.extract(requestPort8080);
+ assertEquals(expected, baseString);
+ }
+
+ @Test
+ public void shouldExcludePort443()
+ {
+ String expected = "GET&https%3A%2F%2Fexample.com&oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature%3DOAuth-Signature%26oauth_timestamp%3D123456";
+ String baseString = extractor.extract(requestPort443);
+ assertEquals(expected, baseString);
+ }
+
+ @Test
+ public void shouldExcludePort443_2()
+ {
+ String expected = "GET&https%3A%2F%2Fexample.com%2Ftest&oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature%3DOAuth-Signature%26oauth_timestamp%3D123456";
+ String baseString = extractor.extract(requestPort443_2);
+ assertEquals(expected, baseString);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionIfRquestIsNull()
+ {
+ OAuthRequest nullRequest = null;
+ extractor.extract(nullRequest);
+ }
+
+ @Test(expected = OAuthParametersMissingException.class)
+ public void shouldThrowExceptionIfRquestHasNoOAuthParameters()
+ {
+ OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com");
+ extractor.extract(request);
+ }
+
+ @Test
+ public void shouldProperlyEncodeSpaces()
+ {
+ String expected = "GET&http%3A%2F%2Fexample.com&body%3Dthis%2520param%2520has%2520whitespace%26oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature%3DOAuth-Signature%26oauth_timestamp%3D123456";
+ request.addBodyParameter("body", "this param has whitespace");
+ assertEquals(expected, extractor.extract(request));
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/extractors/HeaderExtractorTest.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/extractors/HeaderExtractorTest.java
new file mode 100644
index 0000000..bdc727c
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/extractors/HeaderExtractorTest.java
@@ -0,0 +1,45 @@
+package org.scribe.extractors;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.scribe.exceptions.*;
+import org.scribe.model.*;
+import org.scribe.test.helpers.*;
+
+public class HeaderExtractorTest
+{
+
+ private HeaderExtractorImpl extractor;
+ private OAuthRequest request;
+
+ @Before
+ public void setup()
+ {
+ request = ObjectMother.createSampleOAuthRequest();
+ extractor = new HeaderExtractorImpl();
+ }
+
+ @Test
+ public void shouldExtractStandardHeader()
+ {
+ String expected = "OAuth oauth_callback=\"http%3A%2F%2Fexample%2Fcallback\", " + "oauth_signature=\"OAuth-Signature\", "
+ + "oauth_consumer_key=\"AS%23%24%5E%2A%40%26\", " + "oauth_timestamp=\"123456\"";
+ String header = extractor.extract(request);
+ assertEquals(expected, header);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldExceptionIfRequestIsNull()
+ {
+ OAuthRequest nullRequest = null;
+ extractor.extract(nullRequest);
+ }
+
+ @Test(expected = OAuthParametersMissingException.class)
+ public void shouldExceptionIfRequestHasNoOAuthParams()
+ {
+ OAuthRequest emptyRequest = new OAuthRequest(Verb.GET, "http://example.com");
+ extractor.extract(emptyRequest);
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/extractors/JsonTokenExtractorTest.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/extractors/JsonTokenExtractorTest.java
new file mode 100644
index 0000000..412e131
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/extractors/JsonTokenExtractorTest.java
@@ -0,0 +1,31 @@
+package org.scribe.extractors;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.scribe.model.*;
+
+public class JsonTokenExtractorTest
+{
+ private String response = "'{ \"access_token\":\"I0122HHJKLEM21F3WLPYHDKGKZULAUO4SGMV3ABKFTDT3T3X\"}'";
+ private JsonTokenExtractor extractor = new JsonTokenExtractor();
+
+ @Test
+ public void shouldParseResponse()
+ {
+ Token token = extractor.extract(response);
+ assertEquals(token.getToken(), "I0122HHJKLEM21F3WLPYHDKGKZULAUO4SGMV3ABKFTDT3T3X");
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void shouldThrowExceptionIfForNullParameters()
+ {
+ extractor.extract(null);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void shouldThrowExceptionIfForEmptyStrings()
+ {
+ extractor.extract("");
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/extractors/TokenExtractor20Test.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/extractors/TokenExtractor20Test.java
new file mode 100644
index 0000000..0fde22f
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/extractors/TokenExtractor20Test.java
@@ -0,0 +1,67 @@
+package org.scribe.extractors;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.scribe.exceptions.*;
+import org.scribe.model.*;
+
+public class TokenExtractor20Test
+{
+
+ private TokenExtractor20Impl extractor;
+
+ @Before
+ public void setup()
+ {
+ extractor = new TokenExtractor20Impl();
+ }
+
+ @Test
+ public void shouldExtractTokenFromOAuthStandardResponse()
+ {
+ String response = "access_token=166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE";
+ Token extracted = extractor.extract(response);
+ assertEquals("166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE", extracted.getToken());
+ assertEquals("", extracted.getSecret());
+ }
+
+ @Test
+ public void shouldExtractTokenFromResponseWithExpiresParam()
+ {
+ String response = "access_token=166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE&expires=5108";
+ Token extracted = extractor.extract(response);
+ assertEquals("166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE", extracted.getToken());
+ assertEquals("", extracted.getSecret());
+ }
+
+ @Test
+ public void shouldExtractTokenFromResponseWithManyParameters()
+ {
+ String response = "access_token=foo1234&other_stuff=yeah_we_have_this_too&number=42";
+ Token extracted = extractor.extract(response);
+ assertEquals("foo1234", extracted.getToken());
+ assertEquals("", extracted.getSecret());
+ }
+
+ @Test(expected = OAuthException.class)
+ public void shouldThrowExceptionIfTokenIsAbsent()
+ {
+ String response = "&expires=5108";
+ extractor.extract(response);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionIfResponseIsNull()
+ {
+ String response = null;
+ extractor.extract(response);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionIfResponseIsEmptyString()
+ {
+ String response = "";
+ extractor.extract(response);
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/extractors/TokenExtractorTest.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/extractors/TokenExtractorTest.java
new file mode 100644
index 0000000..aca5ad1
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/extractors/TokenExtractorTest.java
@@ -0,0 +1,83 @@
+package org.scribe.extractors;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.scribe.exceptions.*;
+import org.scribe.model.*;
+
+public class TokenExtractorTest
+{
+
+ private TokenExtractorImpl extractor;
+
+ @Before
+ public void setup()
+ {
+ extractor = new TokenExtractorImpl();
+ }
+
+ @Test
+ public void shouldExtractTokenFromOAuthStandardResponse()
+ {
+ String response = "oauth_token=hh5s93j4hdidpola&oauth_token_secret=hdhd0244k9j7ao03";
+ Token extracted = extractor.extract(response);
+ assertEquals("hh5s93j4hdidpola", extracted.getToken());
+ assertEquals("hdhd0244k9j7ao03", extracted.getSecret());
+ }
+
+ @Test
+ public void shouldExtractTokenFromInvertedOAuthStandardResponse()
+ {
+ String response = "oauth_token_secret=hh5s93j4hdidpola&oauth_token=hdhd0244k9j7ao03";
+ Token extracted = extractor.extract(response);
+ assertEquals("hh5s93j4hdidpola", extracted.getSecret());
+ assertEquals("hdhd0244k9j7ao03", extracted.getToken());
+ }
+
+ @Test
+ public void shouldExtractTokenFromResponseWithCallbackConfirmed()
+ {
+ String response = "oauth_token=hh5s93j4hdidpola&oauth_token_secret=hdhd0244k9j7ao03&callback_confirmed=true";
+ Token extracted = extractor.extract(response);
+ assertEquals("hh5s93j4hdidpola", extracted.getToken());
+ assertEquals("hdhd0244k9j7ao03", extracted.getSecret());
+ }
+
+ @Test
+ public void shouldExtractTokenWithEmptySecret()
+ {
+ String response = "oauth_token=hh5s93j4hdidpola&oauth_token_secret=";
+ Token extracted = extractor.extract(response);
+ assertEquals("hh5s93j4hdidpola", extracted.getToken());
+ assertEquals("", extracted.getSecret());
+ }
+
+ @Test(expected = OAuthException.class)
+ public void shouldThrowExceptionIfTokenIsAbsent()
+ {
+ String response = "oauth_secret=hh5s93j4hdidpola&callback_confirmed=true";
+ extractor.extract(response);
+ }
+
+ @Test(expected = OAuthException.class)
+ public void shouldThrowExceptionIfSecretIsAbsent()
+ {
+ String response = "oauth_token=hh5s93j4hdidpola&callback_confirmed=true";
+ extractor.extract(response);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionIfResponseIsNull()
+ {
+ String response = null;
+ extractor.extract(response);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionIfResponseIsEmptyString()
+ {
+ String response = "";
+ extractor.extract(response);
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/ConnectionStub.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/ConnectionStub.java
new file mode 100644
index 0000000..7e93313
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/ConnectionStub.java
@@ -0,0 +1,86 @@
+package org.scribe.model;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+public class ConnectionStub extends HttpURLConnection
+{
+
+ private Map headers = new HashMap();
+ private Map> responseHeaders = new HashMap>();
+ private int inputStreamCalled = 0;
+
+ public ConnectionStub() throws Exception
+ {
+ super(new URL("http://example.com"));
+ }
+
+ @Override
+ public void setRequestProperty(String key, String value)
+ {
+ headers.put(key, value);
+ }
+
+ @Override
+ public String getRequestProperty(String s)
+ {
+ return headers.get(s);
+ }
+
+ public Map getHeaders()
+ {
+ return headers;
+ }
+
+ @Override
+ public int getResponseCode() throws IOException
+ {
+ return 200;
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException
+ {
+ inputStreamCalled++;
+ return new ByteArrayInputStream("contents".getBytes());
+ }
+
+ public int getTimesCalledInpuStream()
+ {
+ return inputStreamCalled;
+ }
+
+ @Override
+ public OutputStream getOutputStream() throws IOException
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ baos.write("contents".getBytes());
+ return baos;
+ }
+
+ @Override
+ public Map> getHeaderFields()
+ {
+ return responseHeaders;
+ }
+
+ public void addResponseHeader(String key, String value)
+ {
+ responseHeaders.put(key, Arrays.asList(value));
+ }
+
+ public void connect() throws IOException
+ {
+ }
+
+ public void disconnect()
+ {
+ }
+
+ public boolean usingProxy()
+ {
+ return false;
+ }
+
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/OAuthRequestTest.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/OAuthRequestTest.java
new file mode 100644
index 0000000..1ea2f2f
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/OAuthRequestTest.java
@@ -0,0 +1,34 @@
+package org.scribe.model;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+public class OAuthRequestTest
+{
+
+ private OAuthRequest request;
+
+ @Before
+ public void setup()
+ {
+ request = new OAuthRequest(Verb.GET, "http://example.com");
+ }
+
+ @Test
+ public void shouldAddOAuthParamters()
+ {
+ request.addOAuthParameter(OAuthConstants.TOKEN, "token");
+ request.addOAuthParameter(OAuthConstants.NONCE, "nonce");
+ request.addOAuthParameter(OAuthConstants.TIMESTAMP, "ts");
+ request.addOAuthParameter(OAuthConstants.SCOPE, "feeds");
+
+ assertEquals(4, request.getOauthParameters().size());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionIfParameterIsNotOAuth()
+ {
+ request.addOAuthParameter("otherParam", "value");
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/ParameterListTest.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/ParameterListTest.java
new file mode 100644
index 0000000..657e8e2
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/ParameterListTest.java
@@ -0,0 +1,91 @@
+package org.scribe.model;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+
+/**
+ * @author: Pablo Fernandez
+ */
+public class ParameterListTest
+{
+ private ParameterList params;
+
+ @Before
+ public void setup()
+ {
+ this.params = new ParameterList();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionWhenAppendingNullMapToQuerystring()
+ {
+ String url = null;
+ params.appendTo(url);
+ }
+
+ @Test
+ public void shouldAppendNothingToQuerystringIfGivenEmptyMap()
+ {
+ String url = "http://www.example.com";
+ Assert.assertEquals(url, params.appendTo(url));
+ }
+
+ @Test
+ public void shouldAppendParametersToSimpleUrl()
+ {
+ String url = "http://www.example.com";
+ String expectedUrl = "http://www.example.com?param1=value1¶m2=value%20with%20spaces";
+
+ params.add("param1", "value1");
+ params.add("param2", "value with spaces");
+
+ url = params.appendTo(url);
+ Assert.assertEquals(url, expectedUrl);
+ }
+
+ @Test
+ public void shouldAppendParametersToUrlWithQuerystring()
+ {
+ String url = "http://www.example.com?already=present";
+ String expectedUrl = "http://www.example.com?already=present¶m1=value1¶m2=value%20with%20spaces";
+
+ params.add("param1", "value1");
+ params.add("param2", "value with spaces");
+
+ url = params.appendTo(url);
+ Assert.assertEquals(url, expectedUrl);
+ }
+
+ @Test
+ public void shouldProperlySortParameters()
+ {
+ params.add("param1", "v1");
+ params.add("param6", "v2");
+ params.add("a_param", "v3");
+ params.add("param2", "v4");
+ Assert.assertEquals("a_param=v3¶m1=v1¶m2=v4¶m6=v2", params.sort().asFormUrlEncodedString());
+ }
+
+ @Test
+ public void shouldProperlySortParametersWithTheSameName()
+ {
+ params.add("param1", "v1");
+ params.add("param6", "v2");
+ params.add("a_param", "v3");
+ params.add("param1", "v4");
+ Assert.assertEquals("a_param=v3¶m1=v1¶m1=v4¶m6=v2", params.sort().asFormUrlEncodedString());
+ }
+
+ @Test
+ public void shouldNotModifyTheOriginalParameterList()
+ {
+ params.add("param1", "v1");
+ params.add("param6", "v2");
+
+ assertNotSame(params, params.sort());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/RequestTest.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/RequestTest.java
new file mode 100644
index 0000000..c473e77
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/RequestTest.java
@@ -0,0 +1,128 @@
+package org.scribe.model;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+public class RequestTest
+{
+ private Request getRequest;
+ private Request postRequest;
+ private ConnectionStub connection;
+
+ @Before
+ public void setup() throws Exception
+ {
+ connection = new ConnectionStub();
+ postRequest = new Request(Verb.POST, "http://example.com");
+ postRequest.addBodyParameter("param", "value");
+ postRequest.addBodyParameter("param with spaces", "value with spaces");
+ postRequest.setConnection(connection);
+ getRequest = new Request(Verb.GET, "http://example.com?qsparam=value&other+param=value+with+spaces");
+ getRequest.setConnection(connection);
+ }
+
+ @Test
+ public void shouldSetRequestVerb()
+ {
+ getRequest.send();
+ assertEquals("GET", connection.getRequestMethod());
+ }
+
+ @Test
+ public void shouldGetQueryStringParameters()
+ {
+ assertEquals(2, getRequest.getQueryStringParams().size());
+ assertEquals(0, postRequest.getQueryStringParams().size());
+ assertTrue(getRequest.getQueryStringParams().contains(new Parameter("qsparam", "value")));
+ }
+
+ @Test
+ public void shouldAddRequestHeaders()
+ {
+ getRequest.addHeader("Header", "1");
+ getRequest.addHeader("Header2", "2");
+ getRequest.send();
+ assertEquals(2, getRequest.getHeaders().size());
+ assertEquals(2, connection.getHeaders().size());
+ }
+
+ @Test
+ public void shouldSetBodyParamsAndAddContentLength()
+ {
+ assertEquals("param=value¶m%20with%20spaces=value%20with%20spaces", postRequest.getBodyContents());
+ postRequest.send();
+ assertTrue(connection.getHeaders().containsKey("Content-Length"));
+ }
+
+ @Test
+ public void shouldSetPayloadAndHeaders()
+ {
+ postRequest.addPayload("PAYLOAD");
+ postRequest.send();
+ assertEquals("PAYLOAD", postRequest.getBodyContents());
+ assertTrue(connection.getHeaders().containsKey("Content-Length"));
+ }
+
+ @Test
+ public void shouldAllowAddingQuerystringParametersAfterCreation()
+ {
+ Request request = new Request(Verb.GET, "http://example.com?one=val");
+ request.addQuerystringParameter("two", "other val");
+ request.addQuerystringParameter("more", "params");
+ assertEquals(3, request.getQueryStringParams().size());
+ }
+
+ @Test
+ public void shouldReturnTheCompleteUrl()
+ {
+ Request request = new Request(Verb.GET, "http://example.com?one=val");
+ request.addQuerystringParameter("two", "other val");
+ request.addQuerystringParameter("more", "params");
+ assertEquals("http://example.com?one=val&two=other%20val&more=params", request.getCompleteUrl());
+ }
+
+ @Test
+ public void shouldHandleQueryStringSpaceEncodingProperly()
+ {
+ assertTrue(getRequest.getQueryStringParams().contains(new Parameter("other param","value with spaces")));
+ }
+
+ @Test
+ public void shouldAutomaticallyAddContentTypeForPostRequestsWithBytePayload()
+ {
+ postRequest.addPayload("PAYLOAD".getBytes());
+ postRequest.send();
+ assertEquals(Request.DEFAULT_CONTENT_TYPE, connection.getHeaders().get("Content-Type"));
+ }
+
+ @Test
+ public void shouldAutomaticallyAddContentTypeForPostRequestsWithStringPayload()
+ {
+ postRequest.addPayload("PAYLOAD");
+ postRequest.send();
+ assertEquals(Request.DEFAULT_CONTENT_TYPE, connection.getHeaders().get("Content-Type"));
+ }
+
+ @Test
+ public void shouldAutomaticallyAddContentTypeForPostRequestsWithBodyParameters()
+ {
+ postRequest.send();
+ assertEquals(Request.DEFAULT_CONTENT_TYPE, connection.getHeaders().get("Content-Type"));
+ }
+
+ @Test
+ public void shouldBeAbleToOverrideItsContentType()
+ {
+ postRequest.addHeader("Content-Type", "my-content-type");
+ postRequest.send();
+ assertEquals("my-content-type", connection.getHeaders().get("Content-Type"));
+ }
+
+ @Test
+ public void shouldNotAddContentTypeForGetRequests()
+ {
+ getRequest.send();
+ assertFalse(connection.getHeaders().containsKey("Content-Type"));
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/ResponseTest.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/ResponseTest.java
new file mode 100644
index 0000000..a58fc03
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/ResponseTest.java
@@ -0,0 +1,75 @@
+package org.scribe.model;
+
+import static org.junit.Assert.*;
+
+import java.io.*;
+
+import org.junit.*;
+
+public class ResponseTest
+{
+
+ private Response response;
+ private ConnectionStub connection;
+
+ @Before
+ public void setup() throws Exception
+ {
+ connection = new ConnectionStub();
+ connection.addResponseHeader("one", "one");
+ connection.addResponseHeader("two", "two");
+ response = new Response(connection);
+ }
+
+ @Test
+ public void shouldPopulateResponseHeaders()
+ {
+ assertEquals(2, response.getHeaders().size());
+ assertEquals("one", response.getHeader("one"));
+ }
+
+ @Test
+ public void shouldParseBodyContents()
+ {
+ assertEquals("contents", response.getBody());
+ assertEquals(1, connection.getTimesCalledInpuStream());
+ }
+
+ @Test
+ public void shouldParseBodyContentsOnlyOnce()
+ {
+ assertEquals("contents", response.getBody());
+ assertEquals("contents", response.getBody());
+ assertEquals("contents", response.getBody());
+ assertEquals(1, connection.getTimesCalledInpuStream());
+ }
+
+ @Test
+ public void shouldHandleAConnectionWithErrors() throws Exception
+ {
+ Response errResponse = new Response(new FaultyConnection());
+ assertEquals(400, errResponse.getCode());
+ assertEquals("errors", errResponse.getBody());
+ }
+
+ private static class FaultyConnection extends ConnectionStub
+ {
+
+ public FaultyConnection() throws Exception
+ {
+ super();
+ }
+
+ @Override
+ public InputStream getErrorStream()
+ {
+ return new ByteArrayInputStream("errors".getBytes());
+ }
+
+ @Override
+ public int getResponseCode() throws IOException
+ {
+ return 400;
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/TokenTest.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/TokenTest.java
new file mode 100644
index 0000000..dff59cc
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/model/TokenTest.java
@@ -0,0 +1,44 @@
+package org.scribe.model;
+
+import static junit.framework.Assert.*;
+import org.junit.*;
+
+public class TokenTest
+{
+ @Test
+ public void shouldTestEqualityBasedOnTokenAndSecret() throws Exception
+ {
+ Token expected = new Token("access","secret");
+ Token actual = new Token("access","secret");
+
+ assertEquals(expected, actual);
+ assertEquals(actual, actual);
+ }
+
+ @Test
+ public void shouldNotDependOnRawString() throws Exception
+ {
+ Token expected = new Token("access","secret", "raw_string");
+ Token actual = new Token("access","secret", "different_raw_string");
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void shouldReturnSameHashCodeForEqualObjects() throws Exception
+ {
+ Token expected = new Token("access","secret");
+ Token actual = new Token("access","secret");
+
+ assertEquals(expected.hashCode(), actual.hashCode());
+ }
+
+ @Test
+ public void shouldNotBeEqualToNullOrOtherObjects() throws Exception
+ {
+ Token expected = new Token("access","secret","response");
+
+ assertNotSame(expected, null);
+ assertNotSame(expected, new Object());
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/services/HMACSha1SignatureServiceTest.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/services/HMACSha1SignatureServiceTest.java
new file mode 100644
index 0000000..ec058a7
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/services/HMACSha1SignatureServiceTest.java
@@ -0,0 +1,59 @@
+package org.scribe.services;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.scribe.exceptions.*;
+
+public class HMACSha1SignatureServiceTest
+{
+
+ private HMACSha1SignatureService service;
+
+ @Before
+ public void setup()
+ {
+ service = new HMACSha1SignatureService();
+ }
+
+ @Test
+ public void shouldReturnSignatureMethodString()
+ {
+ String expected = "HMAC-SHA1";
+ assertEquals(expected, service.getSignatureMethod());
+ }
+
+ @Test
+ public void shouldReturnSignature()
+ {
+ String apiSecret = "api secret";
+ String tokenSecret = "token secret";
+ String baseString = "base string";
+ String signature = "uGymw2KHOTWI699YEaoi5xyLT50=";
+ assertEquals(signature, service.getSignature(baseString, apiSecret, tokenSecret));
+ }
+
+ @Test(expected = OAuthException.class)
+ public void shouldThrowExceptionIfBaseStringIsNull()
+ {
+ service.getSignature(null, "apiSecret", "tokenSecret");
+ }
+
+ @Test(expected = OAuthException.class)
+ public void shouldThrowExceptionIfBaseStringIsEmpty()
+ {
+ service.getSignature(" ", "apiSecret", "tokenSecret");
+ }
+
+ @Test(expected = OAuthException.class)
+ public void shouldThrowExceptionIfApiSecretIsNull()
+ {
+ service.getSignature("base string", null, "tokenSecret");
+ }
+
+ @Test(expected = OAuthException.class)
+ public void shouldThrowExceptionIfApiSecretIsEmpty()
+ {
+ service.getSignature("base string", " ", "tokenSecret");
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/services/RSASha1SignatureServiceTest.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/services/RSASha1SignatureServiceTest.java
new file mode 100644
index 0000000..2e78e84
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/services/RSASha1SignatureServiceTest.java
@@ -0,0 +1,67 @@
+package org.scribe.services;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import javax.xml.bind.DatatypeConverter;
+import java.security.*;
+import java.security.spec.*;
+
+public class RSASha1SignatureServiceTest
+{
+
+ RSASha1SignatureService service = new RSASha1SignatureService(getPrivateKey());
+
+ @Test
+ public void shouldReturnSignatureMethodString()
+ {
+ String expected = "RSA-SHA1";
+ assertEquals(expected, service.getSignatureMethod());
+ }
+
+ @Test
+ public void shouldReturnSignature()
+ {
+ String apiSecret = "api secret";
+ String tokenSecret = "token secret";
+ String baseString = "base string";
+ String signature = "LUNRzQAlpdNyM9mLXm96Va6g/qVNnEAb7p7K1KM0g8IopOFQJPoOO7cvppgt7w3QyhijWJnCmvqXaaIAGrqvdyr3fIzBULh8D/iZQUNLMi08GCOA34P81XBvsc7A5uJjPDsGhJg2MzoVJ8nWJhU/lMMk4c92S1WGskeoDofRwpo=";
+ assertEquals(signature, service.getSignature(baseString, apiSecret, tokenSecret));
+ }
+
+ /**
+ *Created primary key using openssl.
+ *
+ * openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj '/C=GB/ST=/L=Manchester/CN=www.example.com' -keyout myrsakey.pem -out /tmp/myrsacert.pem
+ * openssl pkcs8 -in myrsakey.pem -topk8 -nocrypt -out myrsakey.pk8
+ */
+ private static PrivateKey getPrivateKey()
+ {
+ String str = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMPQ5BCMxlUq2TYy\n"+
+ "iRIoEUsz6HGTJhHuasS2nx1Se4Co3lxwxyubVdFj8AuhHNJSmJvjlpbTsGOjLZpr\n"+
+ "HyDEDdJmf1Fensh1MhUnBZ4a7uLrZrKzFHHJdamX9pxapB89vLeHlCot9hVXdrZH\n"+
+ "nNtg6FdmRKH/8gbs8iDyIayFvzYDAgMBAAECgYA+c9MpTBy9cQsR9BAvkEPjvkx2\n"+
+ "XL4ZnfbDgpNA4Nuu7yzsQrPjPomiXMNkkiAFHH67yVxwAlgRjyuuQlgNNTpKvyQt\n"+
+ "XcHxffnU0820VmE23M+L7jg2TlB3+rUnEDmDvCoyjlwGDR6lNb7t7Fgg2iR+iaov\n"+
+ "0iVzz+l9w0slRlyGsQJBAPWXW2m3NmFgqfDxtw8fsKC2y8o17/cnPjozRGtWb8LQ\n"+
+ "g3VCb8kbOFHOYNGazq3M7+wD1qILF2h/HecgK9eQrZ0CQQDMHXoJMfKKbrFrTKgE\n"+
+ "zyggO1gtuT5OXYeFewMEb5AbDI2FfSc2YP7SHij8iQ2HdukBrbTmi6qxh3HmIR58\n"+
+ "I/AfAkEA0Y9vr0tombsUB8cZv0v5OYoBZvCTbMANtzfb4AOHpiKqqbohDOevLQ7/\n"+
+ "SpvgVCmVaDz2PptcRAyEBZ5MCssneQJAB2pmvaDH7Ambfod5bztLfOhLCtY5EkXJ\n"+
+ "n6rZcDbRaHorRhdG7m3VtDKOUKZ2DF7glkQGV33phKukErVPUzlHBwJAScD9TqaG\n"+
+ "wJ3juUsVtujV23SnH43iMggXT7m82STpPGam1hPfmqu2Z0niePFo927ogQ7H1EMJ\n"+
+ "UHgqXmuvk2X/Ww==";
+
+ try
+ {
+ KeyFactory fac = KeyFactory.getInstance("RSA");
+ PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(DatatypeConverter.parseBase64Binary(str));
+ return fac.generatePrivate(privKeySpec);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/services/TimestampServiceTest.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/services/TimestampServiceTest.java
new file mode 100644
index 0000000..352b962
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/services/TimestampServiceTest.java
@@ -0,0 +1,50 @@
+package org.scribe.services;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+public class TimestampServiceTest
+{
+
+ private TimestampServiceImpl service;
+ private TimestampServiceImpl.Timer timerStub;
+
+ @Before
+ public void setup()
+ {
+ service = new TimestampServiceImpl();
+ timerStub = new TimerStub();
+ service.setTimer(timerStub);
+ }
+
+ @Test
+ public void shouldReturnTimestampInSeconds()
+ {
+ String expected = "1000";
+ assertEquals(expected, service.getTimestampInSeconds());
+ }
+
+ @Test
+ public void shouldReturnNonce()
+ {
+ String expected = "1042";
+ assertEquals(expected, service.getNonce());
+ }
+
+ private static class TimerStub extends TimestampServiceImpl.Timer
+ {
+
+ @Override
+ public Long getMilis()
+ {
+ return 1000000L;
+ }
+
+ @Override
+ public Integer getRandomInteger()
+ {
+ return 42;
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/test/helpers/ObjectMother.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/test/helpers/ObjectMother.java
new file mode 100644
index 0000000..abd75cc
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/test/helpers/ObjectMother.java
@@ -0,0 +1,67 @@
+package org.scribe.test.helpers;
+
+import org.scribe.model.*;
+
+public class ObjectMother
+{
+
+ public static OAuthRequest createSampleOAuthRequest()
+ {
+ OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com");
+ request.addOAuthParameter(OAuthConstants.TIMESTAMP, "123456");
+ request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, "AS#$^*@&");
+ request.addOAuthParameter(OAuthConstants.CALLBACK, "http://example/callback");
+ request.addOAuthParameter(OAuthConstants.SIGNATURE, "OAuth-Signature");
+ return request;
+ }
+
+ public static OAuthRequest createSampleOAuthRequestPort80()
+ {
+ OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com:80");
+ request.addOAuthParameter(OAuthConstants.TIMESTAMP, "123456");
+ request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, "AS#$^*@&");
+ request.addOAuthParameter(OAuthConstants.CALLBACK, "http://example/callback");
+ request.addOAuthParameter(OAuthConstants.SIGNATURE, "OAuth-Signature");
+ return request;
+ }
+
+ public static OAuthRequest createSampleOAuthRequestPort80_2()
+ {
+ OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com:80/test");
+ request.addOAuthParameter(OAuthConstants.TIMESTAMP, "123456");
+ request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, "AS#$^*@&");
+ request.addOAuthParameter(OAuthConstants.CALLBACK, "http://example/callback");
+ request.addOAuthParameter(OAuthConstants.SIGNATURE, "OAuth-Signature");
+ return request;
+ }
+
+ public static OAuthRequest createSampleOAuthRequestPort8080()
+ {
+ OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com:8080");
+ request.addOAuthParameter(OAuthConstants.TIMESTAMP, "123456");
+ request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, "AS#$^*@&");
+ request.addOAuthParameter(OAuthConstants.CALLBACK, "http://example/callback");
+ request.addOAuthParameter(OAuthConstants.SIGNATURE, "OAuth-Signature");
+ return request;
+ }
+
+ public static OAuthRequest createSampleOAuthRequestPort443()
+ {
+ OAuthRequest request = new OAuthRequest(Verb.GET, "https://example.com:443");
+ request.addOAuthParameter(OAuthConstants.TIMESTAMP, "123456");
+ request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, "AS#$^*@&");
+ request.addOAuthParameter(OAuthConstants.CALLBACK, "http://example/callback");
+ request.addOAuthParameter(OAuthConstants.SIGNATURE, "OAuth-Signature");
+ return request;
+ }
+
+ public static OAuthRequest createSampleOAuthRequestPort443_2()
+ {
+ OAuthRequest request = new OAuthRequest(Verb.GET, "https://example.com:443/test");
+ request.addOAuthParameter(OAuthConstants.TIMESTAMP, "123456");
+ request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, "AS#$^*@&");
+ request.addOAuthParameter(OAuthConstants.CALLBACK, "http://example/callback");
+ request.addOAuthParameter(OAuthConstants.SIGNATURE, "OAuth-Signature");
+ return request;
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/utils/MapUtilsTest.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/utils/MapUtilsTest.java
new file mode 100644
index 0000000..f44a0f5
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/utils/MapUtilsTest.java
@@ -0,0 +1,35 @@
+package org.scribe.utils;
+
+import java.util.*;
+import org.junit.*;
+
+/**
+ * @author: Pablo Fernandez
+ */
+public class MapUtilsTest
+{
+
+ @Test
+ public void shouldPrettyPrintMap()
+ {
+ Map map = new HashMap();
+ map.put(1, "one");
+ map.put(2, "two");
+ map.put(3, "three");
+ map.put(4, "four");
+ Assert.assertEquals("{ 1 -> one , 2 -> two , 3 -> three , 4 -> four }", MapUtils.toString(map));
+ }
+
+ @Test
+ public void shouldHandleEmptyMap()
+ {
+ Map map = new HashMap();
+ Assert.assertEquals("{}", MapUtils.toString(map));
+ }
+
+ @Test
+ public void shouldHandleNullInputs()
+ {
+ Assert.assertEquals("", MapUtils.toString(null));
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/utils/OAuthEncoderTest.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/utils/OAuthEncoderTest.java
new file mode 100644
index 0000000..cf986a2
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/utils/OAuthEncoderTest.java
@@ -0,0 +1,70 @@
+package org.scribe.utils;
+
+import org.junit.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author: Pablo Fernandez
+ */
+public class OAuthEncoderTest
+{
+ @Test
+ public void shouldPercentEncodeString()
+ {
+ String plain = "this is a test &^";
+ String encoded = "this%20is%20a%20test%20%26%5E";
+ assertEquals(encoded, OAuthEncoder.encode(plain));
+ }
+
+ @Test
+ public void shouldFormURLDecodeString()
+ {
+ String encoded = "this+is+a+test+%26%5E";
+ String plain = "this is a test &^";
+ assertEquals(plain, OAuthEncoder.decode(encoded));
+ }
+
+ @Test
+ public void shouldPercentEncodeAllSpecialCharacters()
+ {
+ String plain = "!*'();:@&=+$,/?#[]";
+ String encoded = "%21%2A%27%28%29%3B%3A%40%26%3D%2B%24%2C%2F%3F%23%5B%5D";
+ assertEquals(encoded, OAuthEncoder.encode(plain));
+ assertEquals(plain, OAuthEncoder.decode(encoded));
+ }
+
+ @Test
+ public void shouldNotPercentEncodeReservedCharacters()
+ {
+ String plain = "abcde123456-._~";
+ String encoded = plain;
+ assertEquals(encoded, OAuthEncoder.encode(plain));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionIfStringToEncodeIsNull()
+ {
+ String toEncode = null;
+ OAuthEncoder.encode(toEncode);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionIfStringToDecodeIsNull()
+ {
+ String toDecode = null;
+ OAuthEncoder.decode(toDecode);
+ }
+
+ @Test
+ public void shouldPercentEncodeCorrectlyTwitterCodingExamples()
+ {
+ // These tests are part of the Twitter dev examples here -> https://dev.twitter.com/docs/auth/percent-encoding-parameters
+ String sources[] = {"Ladies + Gentlemen", "An encoded string!", "Dogs, Cats & Mice"};
+ String encoded[] = {"Ladies%20%2B%20Gentlemen", "An%20encoded%20string%21", "Dogs%2C%20Cats%20%26%20Mice"};
+
+ for(int i = 0; i < sources.length; i++)
+ {
+ Assert.assertEquals(encoded[i], OAuthEncoder.encode(sources[i]));
+ }
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/utils/PreconditionsTest.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/utils/PreconditionsTest.java
new file mode 100644
index 0000000..84bc117
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/utils/PreconditionsTest.java
@@ -0,0 +1,87 @@
+package org.scribe.utils;
+
+import org.junit.*;
+
+public class PreconditionsTest
+{
+
+ private static final String ERROR_MSG = "";
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionForNullObjects()
+ {
+ Preconditions.checkNotNull(null, ERROR_MSG);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionForNullStrings()
+ {
+ Preconditions.checkEmptyString(null, ERROR_MSG);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionForEmptyStrings()
+ {
+ Preconditions.checkEmptyString("", ERROR_MSG);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionForSpacesOnlyStrings()
+ {
+ Preconditions.checkEmptyString(" ", ERROR_MSG);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionForInvalidUrls()
+ {
+ Preconditions.checkValidUrl("this/is/not/a/valid/url", ERROR_MSG);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionForNullUrls()
+ {
+ Preconditions.checkValidUrl(null, ERROR_MSG);
+ }
+
+ @Test
+ public void shouldAllowValidUrls()
+ {
+ Preconditions.checkValidUrl("http://www.example.com", ERROR_MSG);
+ }
+
+ @Test
+ public void shouldAllowSSLUrls()
+ {
+ Preconditions.checkValidUrl("https://www.example.com", ERROR_MSG);
+ }
+
+ @Test
+ public void shouldAllowSpecialCharsInScheme()
+ {
+ Preconditions.checkValidUrl("custom+9.3-1://www.example.com", ERROR_MSG);
+ }
+
+ @Test
+ public void shouldAllowNonStandarProtocolsForAndroid()
+ {
+ Preconditions.checkValidUrl("x-url-custom://www.example.com", ERROR_MSG);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldNotAllowStrangeProtocolNames()
+ {
+ Preconditions.checkValidUrl("$weird*://www.example.com", ERROR_MSG);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldNotAllowUnderscoreInScheme()
+ {
+ Preconditions.checkValidUrl("http_custom://www.example.com", ERROR_MSG);
+ }
+
+ @Test
+ public void shouldAllowOutOfBandAsValidCallbackValue()
+ {
+ Preconditions.checkValidOAuthCallback("oob", ERROR_MSG);
+ }
+}
diff --git a/src/main/resources/scribe-java-project/src/test/java/org/scribe/utils/StreamUtilsTest.java b/src/main/resources/scribe-java-project/src/test/java/org/scribe/utils/StreamUtilsTest.java
new file mode 100644
index 0000000..976914d
--- /dev/null
+++ b/src/main/resources/scribe-java-project/src/test/java/org/scribe/utils/StreamUtilsTest.java
@@ -0,0 +1,29 @@
+package org.scribe.utils;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class StreamUtilsTest
+{
+
+ @Test
+ public void shouldCorrectlyDecodeAStream()
+ {
+ String value = "expected";
+ InputStream is = new ByteArrayInputStream(value.getBytes());
+ String decoded = StreamUtils.getStreamContents(is);
+ assertEquals("expected", decoded);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldFailForNullParameter()
+ {
+ InputStream is = null;
+ StreamUtils.getStreamContents(is);
+ fail("Must throw exception before getting here");
+ }
+}