├── README.md ├── alfresco-api-examples ├── .gitignore ├── README.md ├── config.properties ├── logging.properties ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── alfresco │ └── api │ └── example │ ├── BaseCloudExample.java │ ├── BaseOnPremExample.java │ ├── BasePublicAPIExample.java │ ├── CmisAspectQuery.java │ ├── CmisBasicQuery.java │ ├── CmisCreateDocumentExample.java │ ├── CmisGeographicAspectExample.java │ ├── CmisRepositoryInfoExample.java │ ├── CreateCommentExample.java │ ├── GetSitesExample.java │ ├── LikeExample.java │ ├── model │ ├── Container.java │ ├── ContainerEntry.java │ ├── ContainerList.java │ ├── Entry.java │ ├── List.java │ ├── Network.java │ ├── NetworkEntry.java │ ├── NetworkList.java │ ├── Pagination.java │ ├── Site.java │ ├── SiteEntry.java │ └── SiteList.java │ ├── oauth │ ├── LocalServerReceiver.java │ └── VerificationCodeReceiver.java │ └── util │ └── Config.java └── file-loader ├── .gitignore ├── logging.properties ├── pom.xml └── src └── main └── java └── com └── alfresco └── cmis └── example ├── CloudExampleBase.java ├── ExampleBaseIfc.java ├── LoadFiles.java ├── LocalExampleBase.java ├── model ├── Container.java ├── ContainerEntry.java ├── ContainerList.java ├── Entry.java ├── List.java ├── Network.java ├── NetworkEntry.java ├── NetworkList.java ├── Pagination.java ├── Site.java ├── SiteEntry.java └── SiteList.java └── oauth ├── LocalServerReceiver.java ├── OAuth2ClientCredentials.java └── VerificationCodeReceiver.java /README.md: -------------------------------------------------------------------------------- 1 | # alfresco-api-java-examples 2 | 3 | This project contains two projects with sample code related to hitting the public Alfresco API. 4 | 5 | The first project is alfresco-api-examples. Code in this project can do things like find the user's home network, find the sites the user can see, create folders and documents, and rate and comment on folders and documents. Starting with Alfresco 4.2.d Community Edition, this code can run against either Alfresco on-premise or Alfresco in the cloud. 6 | 7 | The second project is file-loader. It shows how to upload a directory of images from your local machine to either Alfresco in the cloud or your own on-premise Alfresco repository. The point of the example is to show that the code is mostly the same. The parts that are different (how you obtain a CMIS session and how you determine the folder where the files should be uploaded) reside in different ancestor classes. Change the class LoadFiles.java extends depending on whether you want to upload to cloud or on-premise. 8 | 9 | This second example is kind of obsolete now that the Public API is in both on-premise and the cloud. 10 | 11 | ## Requirements 12 | 13 | To run the cloud examples in either project, you'll need an API key and a secret. To get those you must be a registered developer. Sign up for free at http://developer.alfresco.com. 14 | 15 | You will also need an Alfresco Cloud account. Sign up for an Alfresco Cloud account at http://cloud.alfresco.com. 16 | Dependencies 17 | 18 | This project uses Maven to manage dependencies. It uses Google's OAuth2 client for Java for authentication. It also depends on Apache Chemistry OpenCMIS 0.9. The CmisAspectExample? relies on Apache Tika to extract information from JPEG files. All of these will be pulled in by Maven. 19 | 20 | If you are running the file-loader project against an on-premise repository, the code is set up to expect that you've deployed the CMIS & Apache Chemistry in Action content model to your local Alfresco repository. If that's not the case for you, simply change the content type constant to something other than "cmisbook:image". 21 | -------------------------------------------------------------------------------- /alfresco-api-examples/.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | target 3 | .classpath 4 | .project 5 | .settings 6 | -------------------------------------------------------------------------------- /alfresco-api-examples/README.md: -------------------------------------------------------------------------------- 1 | These are simple examples showing how to exercise the Alfresco Public API. With 2 | the release of Alfresco 4.2.d Community Edition, the Public API is now 3 | available on both Alfresco in the cloud and Alfresco on-premise. The difference 4 | is how authentication works and the base part of the URLs. 5 | 6 | You can run these examples against either Alfresco in the cloud or your own 7 | Alfresco server, it is completely up to you. 8 | 9 | To run a given example against Alfresco in the cloud, change the example class to 10 | extend from BaseCloudExample. 11 | 12 | To run a given example against Alfresco on-premise, change the example class to extend 13 | from BaseOnPremExample. 14 | 15 | Before running against either cloud or on-premise 16 | ================================================= 17 | 18 | Edit config.properties. Set site to a test site ID in which you can 19 | create and delete folders and documents. 20 | 21 | If you are running CmisCreateDocumentExample or CmisGeographicAspectExample, set the 22 | folder_name, local_file_path, and local_file_type properties. 23 | 24 | Before running against Alfresco in the cloud 25 | ============================================ 26 | 27 | Before running these examples against Alfresco in the cloud you must first register at: 28 | https://developer.alfresco.com 29 | 30 | Add your API key and secret to config.properties. 31 | 32 | In your application profile on developer.alfresco.com, you must set 33 | your callback URL to http://127.0.0.1:8080/Callback. 34 | 35 | If you want to use a different host, port, or URL for your callback, 36 | you must make the appropriate change to LocalServerReceiver.java. 37 | 38 | Before running against Alfresco on-premise 39 | ========================================== 40 | 41 | Edit host, username, and password. -------------------------------------------------------------------------------- /alfresco-api-examples/config.properties: -------------------------------------------------------------------------------- 1 | #Change this to the ID of a site in which you have collaborator access. 2 | site=alfresco-api-demo 3 | 4 | # Specify a folder to create in the root of the test site 5 | folder_name=test folder 6 | 7 | # Specify a test file and type 8 | local_file_path=/users/jpotts/Documents/sample/sample-a.pdf 9 | local_file_type=application/pdf 10 | 11 | # ON-PREMISE ONLY 12 | host=http://localhost:8080/alfresco 13 | username=admin 14 | password=admin 15 | 16 | # CLOUD ONLY 17 | # Register for your API key and secret at http://www.alfresco.com/develop 18 | api_key=PUT YOURS HERE 19 | api_secret=PUT YOURS HERE 20 | -------------------------------------------------------------------------------- /alfresco-api-examples/logging.properties: -------------------------------------------------------------------------------- 1 | # Properties file which configures the operation of the JDK logging facility. 2 | # The system will look for this config file to be specified as a system property: 3 | # >java -Djava.util.logging.config.file=${project_loc:alfresco-cloud-example}/logging.properties 4 | 5 | # Set up the console handler (uncomment "level" to show more fine-grained messages) 6 | handlers = java.util.logging.ConsoleHandler 7 | #java.util.logging.ConsoleHandler.level = CONFIG 8 | 9 | # Set up logging of HTTP requests and responses (uncomment "level" to show) 10 | #com.google.api.client.http.level = CONFIG 11 | -------------------------------------------------------------------------------- /alfresco-api-examples/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | alfresco-api-examples 4 | alfresco-api-examples 5 | 0.0.1-SNAPSHOT 6 | 7 | src/main/java 8 | 9 | 10 | maven-compiler-plugin 11 | 2.3.2 12 | 13 | 1.6 14 | 1.6 15 | 16 | 17 | 18 | 19 | 20 | 21 | google-releases 22 | Google Releases 23 | https://oss.sonatype.org/content/repositories/google-releases 24 | 25 | 26 | artifacts.alfresco.com 27 | Alfresco Maven Repository 28 | https://artifacts.alfresco.com/nexus/content/groups/public/ 29 | 30 | 31 | repository.apache.org 32 | Apache Maven Repository 33 | https://repository.apache.org/content/groups/public/ 34 | 35 | 36 | 37 | 38 | com.google.oauth-client 39 | google-oauth-client 40 | 1.16.0-rc 41 | 42 | 43 | com.google.http-client 44 | google-http-client-jackson 45 | 1.16.0-rc 46 | 47 | 48 | javax.servlet 49 | servlet-api 50 | 2.5 51 | provided 52 | 53 | 54 | org.mortbay.jetty 55 | jetty 56 | 6.1.26 57 | 58 | 59 | org.codehaus.jackson 60 | jackson-mapper-asl 61 | 1.6.4 62 | 63 | 64 | org.apache.chemistry.opencmis 65 | chemistry-opencmis-client-impl 66 | 0.10.0 67 | 68 | 69 | org.alfresco.cmis.client 70 | alfresco-opencmis-extension 71 | 0.7 72 | 73 | 74 | org.apache.tika 75 | tika-parsers 76 | 1.1 77 | 78 | 79 | org.slf4j 80 | slf4j-nop 81 | 1.6.6 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/BaseCloudExample.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example; 2 | 3 | import java.awt.Desktop; 4 | import java.awt.Desktop.Action; 5 | import java.io.IOException; 6 | import java.net.URI; 7 | import java.util.Arrays; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | import org.apache.chemistry.opencmis.client.api.Repository; 13 | import org.apache.chemistry.opencmis.client.api.Session; 14 | import org.apache.chemistry.opencmis.client.api.SessionFactory; 15 | import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl; 16 | import org.apache.chemistry.opencmis.commons.SessionParameter; 17 | import org.apache.chemistry.opencmis.commons.enums.BindingType; 18 | 19 | import com.alfresco.api.example.oauth.LocalServerReceiver; 20 | import com.alfresco.api.example.oauth.VerificationCodeReceiver; 21 | import com.alfresco.api.example.util.Config; 22 | import com.google.api.client.auth.oauth2.AuthorizationCodeFlow; 23 | import com.google.api.client.auth.oauth2.AuthorizationCodeRequestUrl; 24 | import com.google.api.client.auth.oauth2.BearerToken; 25 | import com.google.api.client.auth.oauth2.ClientParametersAuthentication; 26 | import com.google.api.client.auth.oauth2.Credential; 27 | import com.google.api.client.auth.oauth2.TokenResponse; 28 | import com.google.api.client.http.GenericUrl; 29 | import com.google.api.client.http.HttpRequest; 30 | import com.google.api.client.http.HttpRequestFactory; 31 | import com.google.api.client.http.HttpRequestInitializer; 32 | import com.google.api.client.http.HttpTransport; 33 | import com.google.api.client.http.javanet.NetHttpTransport; 34 | import com.google.api.client.json.JsonFactory; 35 | import com.google.api.client.json.JsonObjectParser; 36 | import com.google.api.client.json.jackson.JacksonFactory; 37 | 38 | /** 39 | * This class contains only the logic specific to using the Alfresco Public API 40 | * against Alfresco in the cloud. 41 | * 42 | * @author jpotts 43 | */ 44 | public class BaseCloudExample extends BasePublicAPIExample { 45 | 46 | public static final String CMIS_URL = "cmis/versions/1.0/atom"; 47 | public static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); 48 | public static final JsonFactory JSON_FACTORY = new JacksonFactory(); 49 | 50 | public static final String ALFRESCO_API_URL = "https://api.alfresco.com/"; 51 | 52 | public static final String TOKEN_SERVER_URL = ALFRESCO_API_URL + "auth/oauth/versions/2/token"; 53 | public static final String AUTHORIZATION_SERVER_URL = ALFRESCO_API_URL + "auth/oauth/versions/2/authorize"; 54 | public static final String SCOPE = "public_api"; 55 | public static final List SCOPES = Arrays.asList(SCOPE); 56 | 57 | private HttpRequestFactory requestFactory; 58 | private Credential credential; 59 | private Session cmisSession; 60 | 61 | public String getAlfrescoAPIUrl() { 62 | return ALFRESCO_API_URL; 63 | } 64 | 65 | public String getAtomPubURL() { 66 | return ALFRESCO_API_URL + CMIS_URL; 67 | } 68 | 69 | public void launchInBrowser( 70 | String browser, String redirectUrl, String clientId, String scope) throws IOException { 71 | 72 | String authorizationUrl = new AuthorizationCodeRequestUrl( 73 | AUTHORIZATION_SERVER_URL, clientId).setRedirectUri(redirectUrl) 74 | .setScopes(Arrays.asList(scope)).build(); 75 | 76 | if (Desktop.isDesktopSupported()) { 77 | Desktop desktop = Desktop.getDesktop(); 78 | if (desktop.isSupported(Action.BROWSE)) { 79 | desktop.browse(URI.create(authorizationUrl)); 80 | return; 81 | } 82 | } 83 | 84 | if (browser != null) { 85 | Runtime.getRuntime().exec(new String[] {browser, authorizationUrl}); 86 | } else { 87 | System.out.println("Open the following address in your favorite browser:"); 88 | System.out.println(" " + authorizationUrl); 89 | } 90 | } 91 | 92 | /** 93 | * Does the OAuth dance by starting up a local server to handle the 94 | * redirect. The credential gets saved off because it needs to be used 95 | * when/if a CMIS session is needed. 96 | * 97 | * @return HttpRequestFactory 98 | */ 99 | public HttpRequestFactory getRequestFactory() { 100 | if (this.requestFactory == null) { 101 | VerificationCodeReceiver receiver = new LocalServerReceiver(); 102 | try { 103 | String redirectUri = receiver.getRedirectUri(); 104 | launchInBrowser("google-chrome", redirectUri, BaseCloudExample.getAPIKey(), SCOPE); 105 | this.credential = authorize(receiver, redirectUri); 106 | 107 | this.requestFactory = HTTP_TRANSPORT.createRequestFactory(new HttpRequestInitializer() { 108 | @Override 109 | public void initialize(HttpRequest request) throws IOException { 110 | credential.initialize(request); 111 | request.setParser(new JsonObjectParser(new JacksonFactory())); 112 | } 113 | }); 114 | 115 | System.out.println("Access token:" + credential.getAccessToken()); 116 | 117 | } catch (Exception e) { 118 | e.printStackTrace(); 119 | } finally { 120 | try { 121 | receiver.stop(); 122 | } catch (Exception e) {} 123 | } 124 | } 125 | return this.requestFactory; 126 | } 127 | 128 | public Credential authorize(VerificationCodeReceiver receiver, String redirectUri) 129 | throws IOException { 130 | 131 | String code = receiver.waitForCode(); 132 | 133 | AuthorizationCodeFlow codeFlow = new AuthorizationCodeFlow.Builder( 134 | BearerToken.authorizationHeaderAccessMethod(), 135 | HTTP_TRANSPORT, 136 | JSON_FACTORY, 137 | new GenericUrl(TOKEN_SERVER_URL), 138 | new ClientParametersAuthentication( 139 | BaseCloudExample.getAPIKey(), BaseCloudExample.getAPISecret()), 140 | BaseCloudExample.getAPIKey(), 141 | AUTHORIZATION_SERVER_URL).setScopes(SCOPES).build(); 142 | 143 | TokenResponse response = codeFlow.newTokenRequest(code) 144 | .setRedirectUri(redirectUri).setScopes(SCOPES).execute(); 145 | 146 | return codeFlow.createAndStoreCredential(response, null); 147 | 148 | } 149 | 150 | /** 151 | * Gets a CMIS Session by connecting to the Alfresco Cloud. 152 | * 153 | * @param accessToken 154 | * @return Session 155 | */ 156 | public Session getCmisSession() { 157 | if (cmisSession == null) { 158 | String accessToken = getCredential().getAccessToken(); 159 | System.out.println("Access token:" + accessToken); 160 | 161 | // default factory implementation 162 | SessionFactory factory = SessionFactoryImpl.newInstance(); 163 | Map parameter = new HashMap(); 164 | 165 | // connection settings 166 | parameter.put(SessionParameter.ATOMPUB_URL, this.getAtomPubURL()); 167 | parameter.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); 168 | parameter.put(SessionParameter.AUTH_HTTP_BASIC, "false"); 169 | parameter.put(SessionParameter.HEADER + ".0", "Authorization: Bearer " + accessToken); 170 | parameter.put(SessionParameter.OBJECT_FACTORY_CLASS, "org.alfresco.cmis.client.impl.AlfrescoObjectFactoryImpl"); 171 | 172 | List repositories = factory.getRepositories(parameter); 173 | 174 | cmisSession = repositories.get(0).createSession(); 175 | } 176 | return cmisSession; 177 | } 178 | 179 | public Credential getCredential() { 180 | if (this.credential == null) { 181 | getRequestFactory(); // Yuck, depending on a side-effect 182 | } 183 | return this.credential; 184 | } 185 | 186 | public static String getAPIKey() { 187 | return Config.getConfig().getProperty("api_key"); 188 | } 189 | 190 | public static String getAPISecret() { 191 | return Config.getConfig().getProperty("api_secret"); 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/BaseOnPremExample.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example; 2 | 3 | import java.io.IOException; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | import org.apache.chemistry.opencmis.client.api.Repository; 9 | import org.apache.chemistry.opencmis.client.api.Session; 10 | import org.apache.chemistry.opencmis.client.api.SessionFactory; 11 | import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl; 12 | import org.apache.chemistry.opencmis.commons.SessionParameter; 13 | import org.apache.chemistry.opencmis.commons.enums.BindingType; 14 | 15 | import com.alfresco.api.example.util.Config; 16 | import com.google.api.client.http.HttpRequest; 17 | import com.google.api.client.http.HttpRequestFactory; 18 | import com.google.api.client.http.HttpRequestInitializer; 19 | import com.google.api.client.http.HttpTransport; 20 | import com.google.api.client.http.javanet.NetHttpTransport; 21 | import com.google.api.client.json.JsonFactory; 22 | import com.google.api.client.json.JsonObjectParser; 23 | import com.google.api.client.json.jackson.JacksonFactory; 24 | 25 | /** 26 | * This class contains only the logic that is specific to using the Public API 27 | * against an Alfresco repository running on-premise (4.2.d or later). 28 | * 29 | * @author jpotts 30 | */ 31 | public class BaseOnPremExample extends BasePublicAPIExample { 32 | 33 | /** 34 | * Change these to match your environment 35 | */ 36 | //public static final String CMIS_URL = "/public/cmis/versions/1.0/atom"; 37 | public static final String CMIS_URL = "/public/cmis/versions/1.1/atom"; 38 | 39 | public static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); 40 | public static final JsonFactory JSON_FACTORY = new JacksonFactory(); 41 | 42 | private HttpRequestFactory requestFactory; 43 | private Session cmisSession; 44 | 45 | public String getAtomPubURL(HttpRequestFactory requestFactory) { 46 | String alfrescoAPIUrl = getAlfrescoAPIUrl(); 47 | String atomPubURL = null; 48 | 49 | try { 50 | atomPubURL = alfrescoAPIUrl + getHomeNetwork() + CMIS_URL; 51 | } catch (IOException ioe) { 52 | System.out.println("Warning: Couldn't determine home network, defaulting to -default-"); 53 | atomPubURL = alfrescoAPIUrl + "-default-" + CMIS_URL; 54 | } 55 | 56 | return atomPubURL; 57 | } 58 | 59 | /** 60 | * Gets a CMIS Session by connecting to the local Alfresco server. 61 | * 62 | * @return Session 63 | */ 64 | public Session getCmisSession() { 65 | if (cmisSession == null) { 66 | // default factory implementation 67 | SessionFactory factory = SessionFactoryImpl.newInstance(); 68 | Map parameter = new HashMap(); 69 | 70 | // connection settings 71 | parameter.put(SessionParameter.ATOMPUB_URL, getAtomPubURL(getRequestFactory())); 72 | parameter.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); 73 | parameter.put(SessionParameter.AUTH_HTTP_BASIC, "true"); 74 | parameter.put(SessionParameter.USER, getUsername()); 75 | parameter.put(SessionParameter.PASSWORD, getPassword()); 76 | parameter.put(SessionParameter.OBJECT_FACTORY_CLASS, "org.alfresco.cmis.client.impl.AlfrescoObjectFactoryImpl"); 77 | 78 | List repositories = factory.getRepositories(parameter); 79 | 80 | cmisSession = repositories.get(0).createSession(); 81 | } 82 | return this.cmisSession; 83 | } 84 | 85 | /** 86 | * Uses basic authentication to create an HTTP request factory. 87 | * 88 | * @return HttpRequestFactory 89 | */ 90 | public HttpRequestFactory getRequestFactory() { 91 | if (this.requestFactory == null) { 92 | this.requestFactory = HTTP_TRANSPORT.createRequestFactory(new HttpRequestInitializer() { 93 | @Override 94 | public void initialize(HttpRequest request) throws IOException { 95 | request.setParser(new JsonObjectParser(new JacksonFactory())); 96 | request.getHeaders().setBasicAuthentication(getUsername(), getPassword()); 97 | } 98 | }); 99 | } 100 | return this.requestFactory; 101 | } 102 | 103 | public String getAlfrescoAPIUrl() { 104 | String host = Config.getConfig().getProperty("host"); 105 | return host + "/api/"; 106 | } 107 | 108 | public String getUsername() { 109 | return Config.getConfig().getProperty("username"); 110 | } 111 | 112 | public String getPassword() { 113 | return Config.getConfig().getProperty("password"); 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/BasePublicAPIExample.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileNotFoundException; 6 | import java.io.IOException; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | import org.apache.chemistry.opencmis.client.api.Document; 11 | import org.apache.chemistry.opencmis.client.api.Folder; 12 | import org.apache.chemistry.opencmis.client.api.Session; 13 | import org.apache.chemistry.opencmis.commons.data.ContentStream; 14 | import org.apache.chemistry.opencmis.commons.exceptions.CmisContentAlreadyExistsException; 15 | import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; 16 | 17 | import com.alfresco.api.example.model.ContainerEntry; 18 | import com.alfresco.api.example.model.ContainerList; 19 | import com.alfresco.api.example.model.NetworkEntry; 20 | import com.alfresco.api.example.model.NetworkList; 21 | import com.alfresco.api.example.util.Config; 22 | import com.google.api.client.http.ByteArrayContent; 23 | import com.google.api.client.http.GenericUrl; 24 | import com.google.api.client.http.HttpContent; 25 | import com.google.api.client.http.HttpRequest; 26 | import com.google.api.client.http.HttpRequestFactory; 27 | 28 | /** 29 | * This class contains constants and methods that are common across 30 | * the Alfresco Public API regardless of where the target repository is 31 | * hosted. 32 | * 33 | * @author jpotts 34 | * 35 | */ 36 | abstract public class BasePublicAPIExample { 37 | public static final String SITES_URL = "/public/alfresco/versions/1/sites/"; 38 | public static final String NODES_URL = "/public/alfresco/versions/1/nodes/"; 39 | 40 | private String homeNetwork; 41 | 42 | /** 43 | * Use the CMIS API to get a handle to the root folder of the 44 | * target site, then create a new folder, then create 45 | * a new document in the new folder 46 | * 47 | * @param cmisSession 48 | * @param parentFolderId 49 | * @param folderName 50 | * @return Folder 51 | * 52 | * @author jpotts 53 | * 54 | */ 55 | public Folder createFolder(String parentFolderId, String folderName) { 56 | Session cmisSession = getCmisSession(); 57 | Folder rootFolder = (Folder) cmisSession.getObject(parentFolderId); 58 | 59 | Folder subFolder = null; 60 | try { 61 | // Making an assumption here that you probably wouldn't normally do 62 | subFolder = (Folder) cmisSession.getObjectByPath(rootFolder.getPath() + "/" + folderName); 63 | System.out.println("Folder already existed!"); 64 | } catch (CmisObjectNotFoundException onfe) { 65 | Map props = new HashMap(); 66 | props.put("cmis:objectTypeId", "cmis:folder"); 67 | props.put("cmis:name", folderName); 68 | subFolder = rootFolder.createFolder(props); 69 | String subFolderId = subFolder.getId(); 70 | System.out.println("Created new folder: " + subFolderId); 71 | } 72 | 73 | return subFolder; 74 | } 75 | 76 | public String getHomeNetwork() throws IOException { 77 | if (this.homeNetwork == null) { 78 | GenericUrl url = new GenericUrl(getAlfrescoAPIUrl()); 79 | 80 | HttpRequest request = getRequestFactory().buildGetRequest(url); 81 | 82 | NetworkList networkList = request.execute().parseAs(NetworkList.class); 83 | System.out.println("Found " + networkList.list.pagination.totalItems + " networks."); 84 | for (NetworkEntry networkEntry : networkList.list.entries) { 85 | if (networkEntry.entry.homeNetwork) { 86 | this.homeNetwork = networkEntry.entry.id; 87 | } 88 | } 89 | 90 | if (this.homeNetwork == null) { 91 | this.homeNetwork = "-default-"; 92 | } 93 | 94 | System.out.println("Your home network appears to be: " + homeNetwork); 95 | } 96 | return this.homeNetwork; 97 | } 98 | 99 | public Document createDocument(Folder parentFolder, 100 | File file, 101 | String fileType) 102 | throws FileNotFoundException { 103 | return createDocument(parentFolder, file, fileType, null); 104 | } 105 | 106 | /** 107 | * Use the CMIS API to create a document in a folder 108 | * 109 | * @param cmisSession 110 | * @param parentFolder 111 | * @param file 112 | * @param fileType 113 | * @param props 114 | * @return 115 | * @throws FileNotFoundException 116 | * 117 | * @author jpotts 118 | * 119 | */ 120 | public Document createDocument(Folder parentFolder, 121 | File file, 122 | String fileType, 123 | Map props) 124 | throws FileNotFoundException { 125 | 126 | Session cmisSession = getCmisSession(); 127 | 128 | String fileName = file.getName(); 129 | 130 | // create a map of properties if one wasn't passed in 131 | if (props == null) { 132 | props = new HashMap(); 133 | } 134 | 135 | // Add the object type ID if it wasn't already 136 | if (props.get("cmis:objectTypeId") == null) { 137 | props.put("cmis:objectTypeId", "cmis:document"); 138 | } 139 | 140 | // Add the name if it wasn't already 141 | if (props.get("cmis:name") == null) { 142 | props.put("cmis:name", fileName); 143 | } 144 | 145 | ContentStream contentStream = cmisSession.getObjectFactory(). 146 | createContentStream( 147 | fileName, 148 | file.length(), 149 | fileType, 150 | new FileInputStream(file) 151 | ); 152 | 153 | Document document = null; 154 | try { 155 | document = parentFolder.createDocument(props, contentStream, null); 156 | System.out.println("Created new document: " + document.getId()); 157 | } catch (CmisContentAlreadyExistsException ccaee) { 158 | document = (Document) cmisSession.getObjectByPath(parentFolder.getPath() + "/" + fileName); 159 | System.out.println("Document already exists: " + fileName); 160 | } 161 | 162 | return document; 163 | } 164 | 165 | /** 166 | * Use the REST API to find the documentLibrary folder for 167 | * the target site 168 | * @return String 169 | * 170 | * @author jpotts 171 | * 172 | */ 173 | public String getRootFolderId(String site) throws IOException { 174 | 175 | GenericUrl containersUrl = new GenericUrl(getAlfrescoAPIUrl() + 176 | getHomeNetwork() + 177 | SITES_URL + 178 | site + 179 | "/containers"); 180 | System.out.println(containersUrl); 181 | HttpRequest request = getRequestFactory().buildGetRequest(containersUrl); 182 | ContainerList containerList = request.execute().parseAs(ContainerList.class); 183 | String rootFolderId = null; 184 | for (ContainerEntry containerEntry : containerList.list.entries) { 185 | if (containerEntry.entry.folderId.equals("documentLibrary")) { 186 | rootFolderId = containerEntry.entry.id; 187 | break; 188 | } 189 | } 190 | return rootFolderId; 191 | } 192 | 193 | /** 194 | * Use the REST API to "like" an object 195 | * 196 | * @param requestFactory 197 | * @param homeNetwork 198 | * @param objectId 199 | * @throws IOException 200 | */ 201 | public void like(String objectId) throws IOException { 202 | GenericUrl likeUrl = new GenericUrl(getAlfrescoAPIUrl() + 203 | getHomeNetwork() + 204 | NODES_URL + 205 | objectId + 206 | "/ratings"); 207 | HttpContent body = new ByteArrayContent("application/json", "{\"id\": \"likes\", \"myRating\": true}".getBytes()); 208 | HttpRequest request = getRequestFactory().buildPostRequest(likeUrl, body); 209 | request.execute(); 210 | System.out.println("You liked: " + objectId); 211 | } 212 | 213 | /** 214 | * Use the REST API to comment on an object 215 | * 216 | * @param requestFactory 217 | * @param homeNetwork 218 | * @param objectId 219 | * @param comment 220 | * @throws IOException 221 | */ 222 | public void comment(String objectId, String comment) throws IOException { 223 | GenericUrl commentUrl = new GenericUrl(getAlfrescoAPIUrl() + 224 | getHomeNetwork() + 225 | NODES_URL + 226 | objectId + 227 | "/comments"); 228 | HttpContent body = new ByteArrayContent("application/json", 229 | ("{\"content\": \"" + comment + "\"}").getBytes()); 230 | HttpRequest request = getRequestFactory().buildPostRequest(commentUrl, body); 231 | request.execute(); 232 | System.out.println("You commented on: " + objectId); 233 | } 234 | 235 | public String getSite() { 236 | return Config.getConfig().getProperty("site"); 237 | } 238 | 239 | public String getFolderName() { 240 | return Config.getConfig().getProperty("folder_name"); 241 | } 242 | 243 | public File getLocalFile() { 244 | String filePath = Config.getConfig().getProperty("local_file_path"); 245 | return new File(filePath); 246 | } 247 | 248 | public String getLocalFileType() { 249 | return Config.getConfig().getProperty("local_file_type"); 250 | } 251 | 252 | abstract public String getAlfrescoAPIUrl(); 253 | abstract public Session getCmisSession(); 254 | abstract public HttpRequestFactory getRequestFactory(); 255 | } 256 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/CmisAspectQuery.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example; 2 | 3 | /** 4 | * An example of how to do a join with a CMIS query to select properties 5 | * defined in an aspect. 6 | * 7 | * @author jpotts 8 | */ 9 | public class CmisAspectQuery extends CmisBasicQuery { 10 | 11 | public static void main(String[] args) { 12 | CmisAspectQuery caqe = new CmisAspectQuery(); 13 | caqe.doExample(); 14 | } 15 | 16 | public void doExample() { 17 | doQuery("SELECT D.cmis:name, T.cm:title, T.cm:description FROM cmis:document" + 18 | " as D join cm:titled as T on D.cmis:objectId = T.cmis:objectId" + 19 | " where D.cmis:name like '%test%'", 5); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/CmisBasicQuery.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example; 2 | 3 | import org.apache.chemistry.opencmis.client.api.ItemIterable; 4 | import org.apache.chemistry.opencmis.client.api.OperationContext; 5 | import org.apache.chemistry.opencmis.client.api.QueryResult; 6 | import org.apache.chemistry.opencmis.client.api.Session; 7 | import org.apache.chemistry.opencmis.client.runtime.OperationContextImpl; 8 | import org.apache.chemistry.opencmis.commons.data.PropertyData; 9 | 10 | /** 11 | * An extremely basic CMIS query example. This is a port of the "Execute a 12 | * Query" example that ships with the Groovy console in the Workbench plus 13 | * an OperationContext to show how to limit the number of results returned. 14 | * 15 | * @author jpotts 16 | */ 17 | public class CmisBasicQuery extends BaseOnPremExample { 18 | public static void main(String[] args) { 19 | CmisBasicQuery sce = new CmisBasicQuery(); 20 | sce.doExample(); 21 | } 22 | 23 | public void doExample() { 24 | doQuery("SELECT cmis:objectId, cmis:name, cmis:contentStreamLength FROM cmis:document", 5); 25 | } 26 | 27 | public void doQuery(String cql, int maxItems) { 28 | Session cmisSession = getCmisSession(); 29 | 30 | OperationContext oc = new OperationContextImpl(); 31 | oc.setMaxItemsPerPage(maxItems); 32 | 33 | ItemIterable results = cmisSession.query(cql, false, oc); 34 | 35 | for (QueryResult result : results) { 36 | for (PropertyData prop : result.getProperties()) { 37 | System.out.println(prop.getQueryName() + ": " + prop.getFirstValue()); 38 | } 39 | System.out.println("--------------------------------------"); 40 | } 41 | 42 | System.out.println("--------------------------------------"); 43 | System.out.println("Total number: " + results.getTotalNumItems()); 44 | System.out.println("Has more: " + results.getHasMoreItems()); 45 | System.out.println("--------------------------------------"); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/CmisCreateDocumentExample.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example; 2 | 3 | import java.io.IOException; 4 | 5 | import org.apache.chemistry.opencmis.client.api.Folder; 6 | 7 | /** 8 | * Shows how to use CMIS to create a document using the Alfresco Public API. 9 | * 10 | * @author jpotts 11 | * 12 | */ 13 | public class CmisCreateDocumentExample extends BaseOnPremExample { 14 | 15 | public static void main(String[] args) { 16 | CmisCreateDocumentExample ccde = new CmisCreateDocumentExample(); 17 | try { 18 | ccde.doExample(); 19 | } catch (Exception e) { 20 | e.printStackTrace(); 21 | } 22 | } 23 | 24 | public void doExample() { 25 | try { 26 | // Find the root folder of our target site 27 | String rootFolderId = getRootFolderId(getSite()); 28 | 29 | // Create a new folder in the root folder 30 | Folder subFolder = createFolder(rootFolderId, getFolderName()); 31 | 32 | // Create a test document in the subFolder 33 | createDocument(subFolder, getLocalFile(), getLocalFileType()); 34 | 35 | } catch (IOException ioe) { 36 | ioe.printStackTrace(); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/CmisGeographicAspectExample.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileNotFoundException; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | import org.apache.chemistry.opencmis.client.api.Folder; 12 | import org.apache.chemistry.opencmis.client.api.Session; 13 | import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; 14 | import org.apache.tika.exception.TikaException; 15 | import org.apache.tika.metadata.Metadata; 16 | import org.apache.tika.parser.ParseContext; 17 | import org.apache.tika.parser.Parser; 18 | import org.apache.tika.parser.jpeg.JpegParser; 19 | import org.xml.sax.ContentHandler; 20 | import org.xml.sax.SAXException; 21 | import org.xml.sax.helpers.DefaultHandler; 22 | 23 | /** 24 | * Shows how to add an aspect to a document. In this case, we're 25 | * using cm:geographic to store the latitude and longitude that is 26 | * set on some jpeg images in a folder. 27 | * 28 | * @author jpotts 29 | * 30 | */ 31 | public class CmisGeographicAspectExample extends BaseOnPremExample { 32 | 33 | public static final String FOLDER_NAME = "images"; 34 | public static final String FILE_PATH = "/users/jpotts/Documents/sample/photos/Berlin"; 35 | public static final String FILE_TYPE = "image/jpeg"; 36 | 37 | /** 38 | * @param args 39 | */ 40 | public static void main(String[] args) { 41 | CmisGeographicAspectExample ccde = new CmisGeographicAspectExample(); 42 | try { 43 | ccde.doExample(); 44 | } catch (Exception e) { 45 | e.printStackTrace(); 46 | } 47 | } 48 | 49 | public void doExample() { 50 | try { 51 | 52 | // Get a CMIS session 53 | Session cmisSession = getCmisSession(); 54 | 55 | // Find the root folder of our target site 56 | String rootFolderId = getRootFolderId(getSite()); 57 | 58 | // Create a new folder in the root folder 59 | Folder subFolder = createFolder(cmisSession, rootFolderId, FOLDER_NAME); 60 | 61 | File dir = new File(FILE_PATH); 62 | if (!dir.exists() || !dir.isDirectory()) { 63 | System.out.println("Bad path specified: " + dir.getPath()); 64 | return; 65 | } 66 | 67 | File[] fileList = dir.listFiles(); 68 | 69 | for (File file : fileList) { 70 | // set up the properties map 71 | Map props = getProperties(file); 72 | 73 | // if we couldn't get the props for some reason, just 74 | // move on to the next one 75 | if (props.isEmpty()) { 76 | continue; 77 | } 78 | 79 | // create the document in the repo 80 | createDocument(subFolder, file, FILE_TYPE, props); 81 | 82 | } 83 | } catch (IOException ioe) { 84 | ioe.printStackTrace(); 85 | } 86 | } 87 | 88 | /** 89 | * Use the CMIS API to get a handle to the root folder of the 90 | * target site, then create a new folder, then create 91 | * a new document in the new folder 92 | * @param cmisSession 93 | * @param parentFolderId 94 | * @param folderName 95 | * @return Folder 96 | */ 97 | public Folder createFolder(Session cmisSession, String parentFolderId, String folderName) { 98 | 99 | Folder rootFolder = (Folder) cmisSession.getObject(parentFolderId); 100 | 101 | Folder subFolder = null; 102 | try { 103 | // Making an assumption here that you probably wouldn't normally do 104 | subFolder = (Folder) cmisSession.getObjectByPath(rootFolder.getPath() + "/" + folderName); 105 | System.out.println("Folder already existed!"); 106 | } catch (CmisObjectNotFoundException onfe) { 107 | Map props = new HashMap(); 108 | props.put("cmis:objectTypeId", "cmis:folder"); 109 | props.put("cmis:name", folderName); 110 | subFolder = rootFolder.createFolder(props); 111 | String subFolderId = subFolder.getId(); 112 | System.out.println("Created new folder: " + subFolderId); 113 | } 114 | 115 | return subFolder; 116 | } 117 | 118 | /** 119 | * Use Apache Tika to read the latitude and longitude from the 120 | * jpegs. 121 | * 122 | * @param file 123 | * @return 124 | * @throws FileNotFoundException 125 | * @throws IOException 126 | */ 127 | public Map getProperties(File file) 128 | throws FileNotFoundException, IOException { 129 | 130 | Map props = new HashMap(); 131 | 132 | //Tika tika = new Tika(); 133 | 134 | String fileName = file.getName(); 135 | System.out.println("File: " + fileName); 136 | InputStream stream = new FileInputStream(file); 137 | try { 138 | Metadata metadata = new Metadata(); 139 | ContentHandler handler = new DefaultHandler(); 140 | Parser parser = new JpegParser(); 141 | ParseContext context = new ParseContext(); 142 | 143 | //String mimeType = tika.detect(stream); // broken for my jpegs 144 | String mimeType = "image/jpeg"; 145 | metadata.set(Metadata.CONTENT_TYPE, mimeType); 146 | 147 | parser.parse(stream, handler, metadata, context); 148 | String lat = metadata.get("geo:lat"); 149 | String lon = metadata.get("geo:long"); 150 | stream.close(); 151 | 152 | // create a map of properties 153 | props.put("cmis:objectTypeId", "cmis:document,P:cm:geographic"); 154 | props.put("cmis:name", fileName); 155 | if (lat != null && lon != null) { 156 | System.out.println("LAT:" + lat); 157 | System.out.println("LON:" + lon); 158 | props.put("cm:latitude", lat); 159 | props.put("cm:longitude", lon); 160 | } 161 | } catch (TikaException te) { 162 | System.out.println("Caught tika exception, skipping"); 163 | } catch (SAXException se) { 164 | System.out.println("Caught SAXException, skipping"); 165 | } finally { 166 | if (stream != null) { 167 | stream.close(); 168 | } 169 | } 170 | return props; 171 | } 172 | 173 | } 174 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/CmisRepositoryInfoExample.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example; 2 | 3 | import org.apache.chemistry.opencmis.client.api.Session; 4 | import org.apache.chemistry.opencmis.commons.data.RepositoryCapabilities; 5 | import org.apache.chemistry.opencmis.commons.data.RepositoryInfo; 6 | 7 | /** 8 | * Simple example that shows how to use the Alfresco Public API to 9 | * retrieve repository information. 10 | * 11 | * @author jpotts 12 | * 13 | */ 14 | public class CmisRepositoryInfoExample extends BaseOnPremExample { 15 | 16 | public static void main(String[] args) { 17 | CmisRepositoryInfoExample crie = new CmisRepositoryInfoExample(); 18 | try { 19 | crie.doExample(); 20 | } catch (Exception e) { 21 | e.printStackTrace(); 22 | } 23 | } 24 | 25 | public void doExample() { 26 | 27 | // Get a CMIS session 28 | Session cmisSession = getCmisSession(); 29 | 30 | // Get the repository info 31 | RepositoryInfo repoInfo = cmisSession.getRepositoryInfo(); 32 | 33 | System.out.println("Product name: " + repoInfo.getProductName()); 34 | System.out.println("Product version: " + repoInfo.getProductVersion()); 35 | System.out.println("Product vendor: " + repoInfo.getVendorName()); 36 | System.out.println("CMIS version supported: " + repoInfo.getCmisVersionSupported()); 37 | 38 | RepositoryCapabilities caps = repoInfo.getCapabilities(); 39 | 40 | System.out.println("Partial list of capabilities..."); 41 | System.out.println("Joins? " + caps.getJoinCapability()); 42 | System.out.println("ACLs? " + caps.getAclCapability()); 43 | System.out.println("Changes? " + caps.getChangesCapability()); 44 | System.out.println("Queries? " + caps.getQueryCapability()); 45 | System.out.println("Content stream updates? " + caps.getContentStreamUpdatesCapability()); 46 | System.out.println("Renditions? " + caps.getRenditionsCapability()); 47 | System.out.println("Multifiling? " + caps.isMultifilingSupported()); 48 | System.out.println("Version-specific filing? " + caps.isVersionSpecificFilingSupported()); 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/CreateCommentExample.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example; 2 | 3 | import java.io.IOException; 4 | 5 | import org.apache.chemistry.opencmis.client.api.Document; 6 | import org.apache.chemistry.opencmis.client.api.Folder; 7 | 8 | /** 9 | * Shows how to use CMIS to create a document using the Alfresco Public API. 10 | * Also uses the REST API to like a folder and comment on a document. 11 | * 12 | * @author jpotts 13 | * 14 | */ 15 | public class CreateCommentExample extends BaseOnPremExample { 16 | 17 | public static void main(String[] args) { 18 | CreateCommentExample ccde = new CreateCommentExample(); 19 | try { 20 | ccde.doExample(); 21 | } catch (Exception e) { 22 | e.printStackTrace(); 23 | } 24 | } 25 | 26 | public void doExample() { 27 | try { 28 | // Find the root folder of our target site 29 | String rootFolderId = getRootFolderId(getSite()); 30 | 31 | // Create a new folder in the root folder 32 | Folder subFolder = createFolder(rootFolderId, getFolderName()); 33 | 34 | // Create a test document in the subFolder 35 | Document document = createDocument(subFolder, getLocalFile(), getLocalFileType(), null); 36 | 37 | // Create a comment on the test document 38 | // NOTE: When dealing with documents, the REST API wants a versionSeriesID! 39 | comment(document.getVersionSeriesId(), "Here is a comment!"); 40 | } catch (IOException ioe) { 41 | ioe.printStackTrace(); 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/GetSitesExample.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example; 2 | 3 | import java.io.IOException; 4 | 5 | import com.alfresco.api.example.model.SiteEntry; 6 | import com.alfresco.api.example.model.SiteList; 7 | import com.google.api.client.http.GenericUrl; 8 | import com.google.api.client.http.HttpRequest; 9 | 10 | /** 11 | * Simple example that shows how to hit the Alfresco Public API with 12 | * the REST API to find the user's home network and to list up to 13 | * 10 sites visible to the user. 14 | * 15 | * @author jpotts 16 | */ 17 | public class GetSitesExample extends BaseOnPremExample { 18 | 19 | public static void main(String[] args) { 20 | GetSitesExample gse = new GetSitesExample(); 21 | gse.doExample(); 22 | } 23 | 24 | public void doExample() { 25 | try { 26 | // Find the user's home network 27 | String homeNetwork = getHomeNetwork(); 28 | 29 | // List some of the sites the user can see 30 | GenericUrl sitesUrl = new GenericUrl(getAlfrescoAPIUrl() + 31 | homeNetwork + 32 | SITES_URL + "?maxItems=10"); 33 | HttpRequest request = getRequestFactory().buildGetRequest(sitesUrl); 34 | SiteList siteList = request.execute().parseAs(SiteList.class); 35 | System.out.println("Up to 10 sites you can see are:"); 36 | for (SiteEntry siteEntry : siteList.list.entries) { 37 | System.out.println(siteEntry.entry.id); 38 | } 39 | } catch (IOException ioe) { 40 | ioe.printStackTrace(); 41 | } 42 | System.out.println("Done!"); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/LikeExample.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example; 2 | 3 | import java.io.IOException; 4 | 5 | import org.apache.chemistry.opencmis.client.api.Folder; 6 | 7 | /** 8 | * Shows how to use CMIS to create a document using the Alfresco Public API. 9 | * Also uses the REST API to like a folder and comment on a document. 10 | * 11 | * @author jpotts 12 | * 13 | */ 14 | public class LikeExample extends BaseOnPremExample { 15 | 16 | public static void main(String[] args) { 17 | LikeExample le = new LikeExample(); 18 | try { 19 | le.doExample(); 20 | } catch (Exception e) { 21 | e.printStackTrace(); 22 | } 23 | } 24 | 25 | public void doExample() { 26 | try { 27 | // Find the root folder of our target site 28 | String rootFolderId = getRootFolderId(getSite()); 29 | 30 | // Create a new folder in the root folder 31 | Folder subFolder = createFolder(rootFolderId, getFolderName()); 32 | 33 | // Like the folder 34 | like(subFolder.getId()); 35 | 36 | } catch (IOException ioe) { 37 | ioe.printStackTrace(); 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/model/Container.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class Container { 9 | 10 | @Key 11 | public String id; 12 | 13 | @Key 14 | public String folderId; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/model/ContainerEntry.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class ContainerEntry extends Entry { 9 | @Key 10 | public Container entry; 11 | } 12 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/model/ContainerList.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class ContainerList { 9 | @Key 10 | public List list; 11 | } 12 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/model/Entry.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example.model; 2 | 3 | /** 4 | * @author jpotts 5 | */ 6 | public class Entry { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/model/List.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example.model; 2 | 3 | import java.util.ArrayList; 4 | 5 | import com.google.api.client.util.Key; 6 | 7 | /** 8 | * @author jpotts 9 | */ 10 | public class List { 11 | @Key 12 | public ArrayList entries; 13 | 14 | @Key 15 | public Pagination pagination; 16 | } 17 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/model/Network.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class Network { 9 | @Key 10 | public String id; 11 | 12 | @Key 13 | public boolean homeNetwork; 14 | 15 | //@Key 16 | //DateTime createdAt; 17 | 18 | @Key 19 | public boolean paidNetwork; 20 | 21 | @Key 22 | public boolean isEnabled; 23 | 24 | @Key 25 | public String subscriptionLevel; 26 | } 27 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/model/NetworkEntry.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class NetworkEntry extends Entry { 9 | @Key 10 | public Network entry; 11 | } 12 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/model/NetworkList.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class NetworkList { 9 | @Key 10 | public List list; 11 | } 12 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/model/Pagination.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example.model; 2 | import com.google.api.client.util.Key; 3 | 4 | /** 5 | * @author jpotts 6 | */ 7 | public class Pagination { 8 | @Key 9 | public int count; 10 | 11 | @Key 12 | public boolean hasMoreItems; 13 | 14 | @Key 15 | public int totalItems; 16 | 17 | @Key 18 | public int skipCount; 19 | 20 | @Key 21 | public int maxItems; 22 | } 23 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/model/Site.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class Site { 9 | 10 | @Key 11 | public String id; 12 | 13 | @Key 14 | public String title; 15 | 16 | @Key 17 | public String visibility; 18 | 19 | @Key 20 | public String description; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/model/SiteEntry.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class SiteEntry extends Entry { 9 | @Key 10 | public Site entry; 11 | } 12 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/model/SiteList.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class SiteList { 9 | @Key 10 | public List list; 11 | } 12 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/oauth/LocalServerReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package com.alfresco.api.example.oauth; 16 | 17 | import org.mortbay.jetty.Connector; 18 | import org.mortbay.jetty.Request; 19 | import org.mortbay.jetty.Server; 20 | import org.mortbay.jetty.handler.AbstractHandler; 21 | 22 | import java.io.IOException; 23 | import java.io.PrintWriter; 24 | 25 | import javax.servlet.http.HttpServletRequest; 26 | import javax.servlet.http.HttpServletResponse; 27 | 28 | /** 29 | * Runs a Jetty server on a free port, waiting for OAuth to redirect to it with the verification 30 | * code. 31 | *

32 | * Mostly copied from oacurl by phopkins@google.com. 33 | *

34 | * 35 | * @author Yaniv Inbar 36 | */ 37 | public final class LocalServerReceiver implements VerificationCodeReceiver { 38 | 39 | private static final String CALLBACK_PATH = "/Callback"; 40 | private static final String LOCALHOST = "127.0.0.1"; 41 | private static final int PORT = 8080; 42 | 43 | /** Server or {@code null} before {@link #getRedirectUri()}. */ 44 | private Server server; 45 | 46 | /** Verification code or {@code null} before received. */ 47 | volatile String code; 48 | 49 | @Override 50 | public String getRedirectUri() throws Exception { 51 | server = new Server(PORT); 52 | for (Connector c : server.getConnectors()) { 53 | c.setHost(LOCALHOST); 54 | } 55 | server.addHandler(new CallbackHandler()); 56 | server.start(); 57 | return "http://" + LOCALHOST + ":" + PORT + CALLBACK_PATH; 58 | } 59 | 60 | @Override 61 | public synchronized String waitForCode() { 62 | try { 63 | this.wait(); 64 | } catch (InterruptedException exception) { 65 | // should not happen 66 | } 67 | return code; 68 | } 69 | 70 | @Override 71 | public void stop() throws Exception { 72 | if (server != null) { 73 | server.stop(); 74 | server = null; 75 | } 76 | } 77 | 78 | /** 79 | * Jetty handler that takes the verifier token passed over from the OAuth provider and stashes it 80 | * where {@link #waitForCode} will find it. 81 | */ 82 | class CallbackHandler extends AbstractHandler { 83 | 84 | @Override 85 | public void handle( 86 | String target, HttpServletRequest request, HttpServletResponse response, int dispatch) 87 | throws IOException { 88 | if (!CALLBACK_PATH.equals(target)) { 89 | return; 90 | } 91 | writeLandingHtml(response); 92 | response.flushBuffer(); 93 | ((Request) request).setHandled(true); 94 | String error = request.getParameter("error"); 95 | if (error != null) { 96 | System.out.println("Authorization failed. Error=" + error); 97 | System.out.println("Quitting."); 98 | System.exit(1); 99 | } 100 | code = request.getParameter("code"); 101 | synchronized (LocalServerReceiver.this) { 102 | LocalServerReceiver.this.notify(); 103 | } 104 | } 105 | 106 | private void writeLandingHtml(HttpServletResponse response) throws IOException { 107 | response.setStatus(HttpServletResponse.SC_OK); 108 | response.setContentType("text/html"); 109 | 110 | PrintWriter doc = response.getWriter(); 111 | doc.println(""); 112 | doc.println("OAuth 2.0 Authentication Token Recieved"); 113 | doc.println(""); 114 | doc.println("Received verification code. Closing..."); 115 | doc.println(""); 122 | doc.println(""); 123 | doc.println(""); 124 | doc.flush(); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/oauth/VerificationCodeReceiver.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example.oauth; 2 | /* 3 | * Copyright (c) 2011 Google Inc. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software distributed under the License 11 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 12 | * or implied. See the License for the specific language governing permissions and limitations under 13 | * the License. 14 | */ 15 | 16 | /** 17 | * Verification code receiver. 18 | * 19 | * @author Yaniv Inbar 20 | */ 21 | public interface VerificationCodeReceiver { 22 | 23 | /** Returns the redirect URI. */ 24 | String getRedirectUri() throws Exception; 25 | 26 | /** Waits for a verification code. */ 27 | String waitForCode(); 28 | 29 | /** Releases any resources and stops any processes started. */ 30 | void stop() throws Exception; 31 | } 32 | -------------------------------------------------------------------------------- /alfresco-api-examples/src/main/java/com/alfresco/api/example/util/Config.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.api.example.util; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.IOException; 5 | import java.util.Properties; 6 | 7 | public class Config { 8 | 9 | private static Properties config; 10 | 11 | public static Properties getConfig() { 12 | if (config == null) { 13 | config = new Properties(); 14 | try { 15 | config.load(new FileInputStream("config.properties")); 16 | } catch (IOException ioe) { 17 | ioe.printStackTrace(); 18 | } 19 | 20 | } 21 | return config; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /file-loader/.gitignore: -------------------------------------------------------------------------------- 1 | .settings 2 | .classpath 3 | .project 4 | bin 5 | target 6 | -------------------------------------------------------------------------------- /file-loader/logging.properties: -------------------------------------------------------------------------------- 1 | # Properties file which configures the operation of the JDK logging facility. 2 | # The system will look for this config file to be specified as a system property: 3 | # >java -Djava.util.logging.config.file=${project_loc:alfresco-cloud-example}/logging.properties 4 | 5 | # Set up the console handler (uncomment "level" to show more fine-grained messages) 6 | handlers = java.util.logging.ConsoleHandler 7 | #java.util.logging.ConsoleHandler.level = CONFIG 8 | 9 | # Set up logging of HTTP requests and responses (uncomment "level" to show) 10 | #com.google.api.client.http.level = CONFIG 11 | -------------------------------------------------------------------------------- /file-loader/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | file-loader 4 | file-loader 5 | 0.0.1-SNAPSHOT 6 | 7 | src/main/java 8 | 9 | 10 | maven-compiler-plugin 11 | 2.3.2 12 | 13 | 1.6 14 | 1.6 15 | 16 | 17 | 18 | 19 | 20 | 21 | google-releases 22 | Google Releases 23 | https://oss.sonatype.org/content/repositories/google-releases 24 | 25 | 26 | artifacts.alfresco.com 27 | Alfresco Maven Repository 28 | https://artifacts.alfresco.com/nexus/content/groups/public/ 29 | 30 | 31 | repository.apache.org 32 | Apache Maven Repository 33 | https://repository.apache.org/content/groups/public/ 34 | 35 | 36 | 37 | 38 | com.google.oauth-client 39 | google-oauth-client 40 | 1.10.1-beta 41 | 42 | 43 | javax.servlet 44 | servlet-api 45 | 2.5 46 | provided 47 | 48 | 49 | org.mortbay.jetty 50 | jetty 51 | 6.1.26 52 | 53 | 54 | org.codehaus.jackson 55 | jackson-mapper-asl 56 | 1.6.4 57 | 58 | 59 | org.apache.chemistry.opencmis 60 | chemistry-opencmis-client-impl 61 | 0.8.0 62 | 63 | 64 | org.alfresco.cmis.client 65 | alfresco-opencmis-extension 66 | 0.2 67 | 68 | 69 | org.apache.tika 70 | tika-parsers 71 | 1.1 72 | 73 | 74 | org.slf4j 75 | slf4j-nop 76 | 1.6.6 77 | 78 | 79 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/CloudExampleBase.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.cmis.example; 2 | 3 | import java.awt.Desktop; 4 | import java.awt.Desktop.Action; 5 | import java.io.IOException; 6 | import java.net.URI; 7 | import java.util.Arrays; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | import org.apache.chemistry.opencmis.client.api.Folder; 13 | import org.apache.chemistry.opencmis.client.api.Repository; 14 | import org.apache.chemistry.opencmis.client.api.Session; 15 | import org.apache.chemistry.opencmis.client.api.SessionFactory; 16 | import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl; 17 | import org.apache.chemistry.opencmis.commons.SessionParameter; 18 | import org.apache.chemistry.opencmis.commons.enums.BindingType; 19 | 20 | import com.alfresco.cmis.example.model.ContainerEntry; 21 | import com.alfresco.cmis.example.model.ContainerList; 22 | import com.alfresco.cmis.example.oauth.LocalServerReceiver; 23 | import com.alfresco.cmis.example.oauth.OAuth2ClientCredentials; 24 | import com.alfresco.cmis.example.oauth.VerificationCodeReceiver; 25 | import com.google.api.client.auth.oauth2.AuthorizationCodeFlow; 26 | import com.google.api.client.auth.oauth2.AuthorizationCodeRequestUrl; 27 | import com.google.api.client.auth.oauth2.BearerToken; 28 | import com.google.api.client.auth.oauth2.ClientParametersAuthentication; 29 | import com.google.api.client.auth.oauth2.Credential; 30 | import com.google.api.client.auth.oauth2.TokenResponse; 31 | import com.google.api.client.http.GenericUrl; 32 | import com.google.api.client.http.HttpRequest; 33 | import com.google.api.client.http.HttpRequestFactory; 34 | import com.google.api.client.http.HttpRequestInitializer; 35 | import com.google.api.client.http.HttpTransport; 36 | import com.google.api.client.http.javanet.NetHttpTransport; 37 | import com.google.api.client.json.JsonFactory; 38 | import com.google.api.client.json.JsonObjectParser; 39 | import com.google.api.client.json.jackson.JacksonFactory; 40 | 41 | /** 42 | * Knows how to provide the values specific to Alfresco in the cloud. Extend this 43 | * class to load files into an existing site you've created in the cloud. 44 | */ 45 | public class CloudExampleBase implements ExampleBaseIfc { 46 | 47 | // Change these to match your network, site, and folder in Alfresco in the Cloud 48 | /** 49 | * Specify the cloud user's home network. In real life you'd probably make an API call to determine this. 50 | */ 51 | public static final String HOME_NETWORK = "alfresco.com"; 52 | 53 | /** 54 | * Specify the short name of the Alfresco cloud site where the files should be uploaded. 55 | */ 56 | public static final String SITE = "alfresco-api-demo"; 57 | 58 | // Probably do not need to change any constants below this 59 | public static final String ALFRESCO_API_URL = "https://api.alfresco.com/"; 60 | public static final String ATOMPUB_URL = ALFRESCO_API_URL + "cmis/versions/1.0/atom"; 61 | public static final String SCOPE = "public_api"; 62 | public static final String CONTENT_TYPE = "cmis:document"; 63 | 64 | public static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); 65 | public static final JsonFactory JSON_FACTORY = new JacksonFactory(); 66 | 67 | public static final String TOKEN_SERVER_URL = ALFRESCO_API_URL + "auth/oauth/versions/2/token"; 68 | public static final String AUTHORIZATION_SERVER_URL = ALFRESCO_API_URL + "auth/oauth/versions/2/authorize"; 69 | public static final String SITES_URL = "/public/alfresco/versions/1/sites"; 70 | 71 | public HttpRequestFactory requestFactory; 72 | public Session cmisSession; 73 | 74 | /** 75 | * Gets a CMIS Session by connecting to the Alfresco Cloud. 76 | * 77 | * @param accessToken 78 | * @return Session 79 | */ 80 | public Session getCmisSession() throws Exception { 81 | if (cmisSession == null) { 82 | // default factory implementation 83 | SessionFactory factory = SessionFactoryImpl.newInstance(); 84 | Map parameter = new HashMap(); 85 | 86 | // connection settings 87 | parameter.put(SessionParameter.ATOMPUB_URL, ATOMPUB_URL); 88 | parameter.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); 89 | parameter.put(SessionParameter.AUTH_HTTP_BASIC, "false"); 90 | parameter.put(SessionParameter.HEADER + ".0", "Authorization: Bearer " + getAccessToken()); 91 | parameter.put(SessionParameter.OBJECT_FACTORY_CLASS, "org.alfresco.cmis.client.impl.AlfrescoObjectFactoryImpl"); 92 | 93 | List repositories = factory.getRepositories(parameter); 94 | 95 | this.cmisSession = repositories.get(0).createSession(); 96 | } 97 | 98 | return this.cmisSession; 99 | } 100 | 101 | /** 102 | * Get the Folder object where the demo folder is to be created. 103 | */ 104 | public Folder getParentFolder(Session cmisSession) throws Exception { 105 | 106 | String rootFolderId = getRootFolderId(this.requestFactory, HOME_NETWORK, SITE); 107 | 108 | Folder folder = (Folder) cmisSession.getObject(rootFolderId); 109 | 110 | return folder; 111 | 112 | } 113 | 114 | /** 115 | * Return the object type ID of the objects we want to create 116 | */ 117 | public String getObjectTypeId() { 118 | return CONTENT_TYPE; 119 | } 120 | 121 | /** 122 | * Get the OAuth2 access token. 123 | * @return 124 | * @throws Exception 125 | */ 126 | public String getAccessToken() throws Exception { 127 | String accessToken = ""; 128 | // authorization 129 | VerificationCodeReceiver receiver = new LocalServerReceiver(); 130 | try { 131 | String redirectUri = receiver.getRedirectUri(); 132 | launchInBrowser("google-chrome", redirectUri, OAuth2ClientCredentials.CLIENT_ID, SCOPE); 133 | final Credential credential = authorize(receiver, redirectUri); 134 | 135 | this.requestFactory = HTTP_TRANSPORT.createRequestFactory(new HttpRequestInitializer() { 136 | @Override 137 | public void initialize(HttpRequest request) throws IOException { 138 | credential.initialize(request); 139 | request.setParser(new JsonObjectParser(JSON_FACTORY)); 140 | } 141 | }); 142 | 143 | accessToken = credential.getAccessToken(); 144 | 145 | System.out.println("Access token:" + accessToken); 146 | 147 | } catch (Exception e) { 148 | e.printStackTrace(); 149 | } finally { 150 | receiver.stop(); 151 | } 152 | 153 | return accessToken; 154 | 155 | } 156 | 157 | public Credential authorize(VerificationCodeReceiver receiver, String redirectUri) 158 | throws IOException { 159 | 160 | String code = receiver.waitForCode(); 161 | 162 | AuthorizationCodeFlow codeFlow = new AuthorizationCodeFlow.Builder( 163 | BearerToken.authorizationHeaderAccessMethod(), 164 | HTTP_TRANSPORT, 165 | JSON_FACTORY, 166 | new GenericUrl(TOKEN_SERVER_URL), 167 | new ClientParametersAuthentication( 168 | OAuth2ClientCredentials.CLIENT_ID, OAuth2ClientCredentials.CLIENT_SECRET), 169 | OAuth2ClientCredentials.CLIENT_ID, 170 | AUTHORIZATION_SERVER_URL).setScopes(SCOPE).build(); 171 | 172 | TokenResponse response = codeFlow.newTokenRequest(code) 173 | .setRedirectUri(redirectUri).setScopes(SCOPE).execute(); 174 | 175 | return codeFlow.createAndStoreCredential(response, null); 176 | 177 | } 178 | 179 | public void launchInBrowser( 180 | String browser, String redirectUrl, String clientId, String scope) throws IOException { 181 | 182 | String authorizationUrl = new AuthorizationCodeRequestUrl( 183 | AUTHORIZATION_SERVER_URL, clientId).setRedirectUri(redirectUrl) 184 | .setScopes(Arrays.asList(scope)).build(); 185 | 186 | if (Desktop.isDesktopSupported()) { 187 | Desktop desktop = Desktop.getDesktop(); 188 | if (desktop.isSupported(Action.BROWSE)) { 189 | desktop.browse(URI.create(authorizationUrl)); 190 | return; 191 | } 192 | } 193 | 194 | if (browser != null) { 195 | Runtime.getRuntime().exec(new String[] {browser, authorizationUrl}); 196 | } else { 197 | System.out.println("Open the following address in your favorite browser:"); 198 | System.out.println(" " + authorizationUrl); 199 | } 200 | } 201 | 202 | /** 203 | * Use the REST API to find the documentLibrary folder, then return its ID. 204 | * 205 | * @param requestFactory 206 | * @param homeNetwork 207 | * @param site 208 | * @return 209 | * @throws IOException 210 | */ 211 | public String getRootFolderId(HttpRequestFactory requestFactory, String homeNetwork, String site) throws IOException { 212 | GenericUrl containersUrl = new GenericUrl(ALFRESCO_API_URL + 213 | homeNetwork + 214 | SITES_URL + 215 | "/" + 216 | site + 217 | "/containers"); 218 | 219 | HttpRequest request = requestFactory.buildGetRequest(containersUrl); 220 | ContainerList containerList = request.execute().parseAs(ContainerList.class); 221 | String rootFolderId = null; 222 | for (ContainerEntry containerEntry : containerList.list.entries) { 223 | if (containerEntry.entry.folderId.equals("documentLibrary")) { 224 | rootFolderId = containerEntry.entry.id; 225 | break; 226 | } 227 | } 228 | return rootFolderId; 229 | } 230 | 231 | } 232 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/ExampleBaseIfc.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.cmis.example; 2 | 3 | import org.apache.chemistry.opencmis.client.api.Folder; 4 | import org.apache.chemistry.opencmis.client.api.Session; 5 | 6 | public interface ExampleBaseIfc { 7 | 8 | public Session getCmisSession() throws Exception; 9 | 10 | public Folder getParentFolder(Session cmisSession) throws Exception; 11 | 12 | public String getObjectTypeId(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/LoadFiles.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.cmis.example; 2 | 3 | 4 | import java.io.File; 5 | import java.io.FileInputStream; 6 | import java.io.FileNotFoundException; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.math.BigDecimal; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | import org.apache.chemistry.opencmis.client.api.Document; 14 | import org.apache.chemistry.opencmis.client.api.Folder; 15 | import org.apache.chemistry.opencmis.client.api.Session; 16 | import org.apache.chemistry.opencmis.commons.data.ContentStream; 17 | import org.apache.chemistry.opencmis.commons.exceptions.CmisContentAlreadyExistsException; 18 | import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; 19 | import org.apache.tika.exception.TikaException; 20 | import org.apache.tika.metadata.Metadata; 21 | import org.apache.tika.parser.ParseContext; 22 | import org.apache.tika.parser.Parser; 23 | import org.apache.tika.parser.jpeg.JpegParser; 24 | import org.xml.sax.ContentHandler; 25 | import org.xml.sax.SAXException; 26 | import org.xml.sax.helpers.DefaultHandler; 27 | 28 | /** 29 | * Loads the images in a local folder into a CMIS repo. Extend CloudExampleBase 30 | * to load into Alfresco in the cloud. Extend LocalExampleBase to load into a local repo. 31 | * 32 | * @author jpotts 33 | * 34 | */ 35 | public class LoadFiles extends CloudExampleBase { 36 | 37 | // Change these constants to fit your set up 38 | 39 | /** 40 | * Local directory containing JPG files 41 | */ 42 | public static final String FILE_PATH = "/users/jpotts/Documents/sample/photos/Berlin"; 43 | 44 | /** 45 | * Code assumes that every file is of the type below 46 | */ 47 | public static final String FILE_TYPE = "image/jpeg"; 48 | 49 | /** 50 | * Files will be uploaded to this folder, which resides in the folder returned 51 | * by super.getParentFolder() 52 | */ 53 | public static final String FOLDER_NAME = "Art"; 54 | 55 | /** 56 | * @param args 57 | */ 58 | public static void main(String[] args) { 59 | LoadFiles lf = new LoadFiles(); 60 | try { 61 | lf.doExample(); 62 | } catch (Exception e) { 63 | e.printStackTrace(); 64 | } 65 | } 66 | 67 | /** 68 | * Uploads all files in a local directory to the CMIS server. 69 | * @throws IOException 70 | */ 71 | public void doExample() 72 | throws IOException { 73 | 74 | // Get a CMIS session 75 | Session cmisSession; 76 | Folder folder; 77 | try { 78 | cmisSession = getCmisSession(); 79 | Folder parentFolder = getParentFolder(cmisSession); 80 | folder = createFolder(cmisSession, parentFolder, FOLDER_NAME); 81 | } catch (Exception e) { 82 | System.out.println(e.getMessage()); 83 | return; 84 | } 85 | 86 | File dir = new File(FILE_PATH); 87 | if (!dir.exists() || !dir.isDirectory()) { 88 | System.out.println("Bad path specified: " + dir.getPath()); 89 | return; 90 | } 91 | 92 | File[] fileList = dir.listFiles(); 93 | 94 | for (File file : fileList) { 95 | // set up the properties map 96 | Map props = getProperties(getObjectTypeId(), file); 97 | 98 | // if we couldn't get the props for some reason, just 99 | // move on to the next one 100 | if (props.isEmpty()) { 101 | continue; 102 | } 103 | 104 | // create the document in the repo 105 | createDocument(cmisSession, folder, file, FILE_TYPE, props); 106 | 107 | } 108 | 109 | } 110 | 111 | /** 112 | * Gets or creates a folder named folderName in the parentFolder. 113 | * @param cmisSession 114 | * @param parentFolder 115 | * @param folderName 116 | * @return 117 | */ 118 | public Folder createFolder(Session cmisSession, Folder parentFolder, String folderName) { 119 | 120 | Folder subFolder = null; 121 | try { 122 | // Making an assumption here that you probably wouldn't normally do 123 | subFolder = (Folder) cmisSession.getObjectByPath(parentFolder.getPath() + "/" + folderName); 124 | System.out.println("Folder already existed!"); 125 | } catch (CmisObjectNotFoundException onfe) { 126 | Map props = new HashMap(); 127 | props.put("cmis:objectTypeId", "cmis:folder"); 128 | props.put("cmis:name", folderName); 129 | subFolder = parentFolder.createFolder(props); 130 | String subFolderId = subFolder.getId(); 131 | System.out.println("Created new folder: " + subFolderId); 132 | } 133 | 134 | return subFolder; 135 | } 136 | 137 | /** 138 | * Returns the properties that need to be set on an object for a given file. 139 | * 140 | * @param file 141 | * @return 142 | * @throws FileNotFoundException 143 | * @throws IOException 144 | */ 145 | public Map getProperties(String objectTypeId, File file) 146 | throws FileNotFoundException, IOException { 147 | 148 | Map props = new HashMap(); 149 | 150 | //Tika tika = new Tika(); 151 | 152 | String fileName = file.getName(); 153 | System.out.println("File: " + fileName); 154 | InputStream stream = new FileInputStream(file); 155 | try { 156 | // if the target type is the CMIS Book image type, let's extract some metadata from the file 157 | // and return them as properties to be set on the object 158 | if (objectTypeId.equals("D:cmisbook:image")) { 159 | 160 | Metadata metadata = new Metadata(); 161 | ContentHandler handler = new DefaultHandler(); 162 | Parser parser = new JpegParser(); 163 | ParseContext context = new ParseContext(); 164 | 165 | //String mimeType = tika.detect(stream); // broken for my jpegs 166 | String mimeType = FILE_TYPE; 167 | metadata.set(Metadata.CONTENT_TYPE, mimeType); 168 | 169 | parser.parse(stream, handler, metadata, context); 170 | String lat = metadata.get("geo:lat"); 171 | String lon = metadata.get("geo:long"); 172 | stream.close(); 173 | 174 | // create a map of properties 175 | 176 | props.put("cmis:objectTypeId", objectTypeId); 177 | props.put("cmis:name", fileName); 178 | if (lat != null && lon != null) { 179 | System.out.println("LAT:" + lat); 180 | System.out.println("LON:" + lon); 181 | props.put("cmisbook:gpsLatitude", BigDecimal.valueOf(Float.parseFloat(lat))); 182 | props.put("cmisbook:gpsLongitude", BigDecimal.valueOf(Float.parseFloat(lon))); 183 | } 184 | } else { 185 | // otherwise, just set the object type and name and be done 186 | props.put("cmis:objectTypeId", objectTypeId); 187 | props.put("cmis:name", fileName); 188 | } 189 | } catch (TikaException te) { 190 | System.out.println("Caught tika exception, skipping"); 191 | } catch (SAXException se) { 192 | System.out.println("Caught SAXException, skipping"); 193 | } finally { 194 | if (stream != null) { 195 | stream.close(); 196 | } 197 | } 198 | return props; 199 | } 200 | 201 | /** 202 | * Use the CMIS API to create a document in a folder 203 | * 204 | * @param cmisSession 205 | * @param parentFolder 206 | * @param file 207 | * @param fileType 208 | * @param props 209 | * @return 210 | * @throws FileNotFoundException 211 | * 212 | * @author jpotts 213 | * 214 | */ 215 | public Document createDocument(Session cmisSession, 216 | Folder parentFolder, 217 | File file, 218 | String fileType, 219 | Map props) 220 | throws FileNotFoundException { 221 | 222 | String fileName = file.getName(); 223 | 224 | // create a map of properties if one wasn't passed in 225 | if (props == null) { 226 | props = new HashMap(); 227 | } 228 | 229 | // Add the object type ID if it wasn't already 230 | if (props.get("cmis:objectTypeId") == null) { 231 | props.put("cmis:objectTypeId", "cmis:document"); 232 | } 233 | 234 | // Add the name if it wasn't already 235 | if (props.get("cmis:name") == null) { 236 | props.put("cmis:name", fileName); 237 | } 238 | 239 | ContentStream contentStream = cmisSession.getObjectFactory(). 240 | createContentStream( 241 | fileName, 242 | file.length(), 243 | fileType, 244 | new FileInputStream(file) 245 | ); 246 | 247 | Document document = null; 248 | try { 249 | document = parentFolder.createDocument(props, contentStream, null); 250 | System.out.println("Created new document: " + document.getId()); 251 | } catch (CmisContentAlreadyExistsException ccaee) { 252 | document = (Document) cmisSession.getObjectByPath(parentFolder.getPath() + "/" + fileName); 253 | System.out.println("Document already exists: " + fileName); 254 | } 255 | 256 | return document; 257 | } 258 | 259 | } 260 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/LocalExampleBase.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.cmis.example; 2 | 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import org.apache.chemistry.opencmis.client.api.Folder; 8 | import org.apache.chemistry.opencmis.client.api.Repository; 9 | import org.apache.chemistry.opencmis.client.api.Session; 10 | import org.apache.chemistry.opencmis.client.api.SessionFactory; 11 | import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl; 12 | import org.apache.chemistry.opencmis.commons.SessionParameter; 13 | import org.apache.chemistry.opencmis.commons.enums.BindingType; 14 | 15 | /** 16 | * Knows how to provide the values specific to Alfresco on-premise, versions 4.2c and earlier. 17 | * Extend this class to load files into Alfresco running on your own server. 18 | * @author jpotts 19 | */ 20 | public class LocalExampleBase implements ExampleBaseIfc { 21 | 22 | // Change these to match your on-premise Alfresco server setup 23 | 24 | /** 25 | * Host domain and port with a trailing slash 26 | */ 27 | public static final String ALFRESCO_API_URL = "http://localhost:8080/"; 28 | 29 | /** 30 | * Username of a user with write access to the FOLDER_PATH 31 | */ 32 | public static final String USER_NAME = "admin"; 33 | 34 | /** 35 | * Password of a user with write access to the FOLDER_PATH 36 | */ 37 | public static final String PASSWORD = "admin"; 38 | 39 | /** 40 | * Folder path 41 | */ 42 | public static final String FOLDER_PATH = "/blend"; 43 | 44 | /** 45 | * The content type that should be used for the uploaded objects. The default below 46 | * Assumes you've deployed the Alfresco model included with the 47 | * CMIS & Apache Chemistry in Action book from Manning, see 48 | * https://github.com/fmui/ApacheChemistryInAction/tree/master/repositories/alfresco 49 | */ 50 | public static final String CONTENT_TYPE = "D:cmisbook:image"; 51 | 52 | // Probably do not need to change any constants below this 53 | 54 | //public static final String ATOMPUB_URL = ALFRESCO_API_URL + "alfresco/cmisatom"; // 4.0 - 4.2c 55 | public static final String ATOMPUB_URL = ALFRESCO_API_URL + "alfresco/api/-default-/public/cmis/versions/1.0/atom"; // 4.2d 56 | 57 | /** 58 | * Gets a CMIS Session by connecting to the Alfresco Cloud. 59 | * 60 | * @param accessToken 61 | * @return Session 62 | */ 63 | public Session getCmisSession() { 64 | // default factory implementation 65 | SessionFactory factory = SessionFactoryImpl.newInstance(); 66 | Map parameter = new HashMap(); 67 | 68 | // connection settings 69 | parameter.put(SessionParameter.ATOMPUB_URL, ATOMPUB_URL); 70 | parameter.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); 71 | parameter.put(SessionParameter.AUTH_HTTP_BASIC, "true"); 72 | parameter.put(SessionParameter.USER, USER_NAME); 73 | parameter.put(SessionParameter.PASSWORD, PASSWORD); 74 | parameter.put(SessionParameter.OBJECT_FACTORY_CLASS, "org.alfresco.cmis.client.impl.AlfrescoObjectFactoryImpl"); 75 | 76 | List repositories = factory.getRepositories(parameter); 77 | 78 | return repositories.get(0).createSession(); 79 | } 80 | 81 | public Folder getParentFolder(Session cmisSession) { 82 | Folder folder = (Folder) cmisSession.getObjectByPath(FOLDER_PATH); 83 | return folder; 84 | } 85 | 86 | public String getObjectTypeId() { 87 | return CONTENT_TYPE; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/model/Container.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.cmis.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class Container { 9 | 10 | @Key 11 | public String id; 12 | 13 | @Key 14 | public String folderId; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/model/ContainerEntry.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.cmis.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class ContainerEntry extends Entry { 9 | @Key 10 | public Container entry; 11 | } 12 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/model/ContainerList.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.cmis.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class ContainerList { 9 | @Key 10 | public List list; 11 | } 12 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/model/Entry.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.cmis.example.model; 2 | 3 | /** 4 | * @author jpotts 5 | */ 6 | public class Entry { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/model/List.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.cmis.example.model; 2 | 3 | import java.util.ArrayList; 4 | 5 | import com.google.api.client.util.Key; 6 | 7 | /** 8 | * @author jpotts 9 | */ 10 | public class List { 11 | @Key 12 | public ArrayList entries; 13 | 14 | @Key 15 | public Pagination pagination; 16 | } 17 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/model/Network.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.cmis.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class Network { 9 | @Key 10 | public String id; 11 | 12 | @Key 13 | public boolean homeNetwork; 14 | 15 | //@Key 16 | //DateTime createdAt; 17 | 18 | @Key 19 | public boolean paidNetwork; 20 | 21 | @Key 22 | public boolean isEnabled; 23 | 24 | @Key 25 | public String subscriptionLevel; 26 | } 27 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/model/NetworkEntry.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.cmis.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class NetworkEntry extends Entry { 9 | @Key 10 | public Network entry; 11 | } 12 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/model/NetworkList.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.cmis.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class NetworkList { 9 | @Key 10 | public List list; 11 | } 12 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/model/Pagination.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.cmis.example.model; 2 | import com.google.api.client.util.Key; 3 | 4 | /** 5 | * @author jpotts 6 | */ 7 | public class Pagination { 8 | @Key 9 | public int count; 10 | 11 | @Key 12 | public boolean hasMoreItems; 13 | 14 | @Key 15 | public int totalItems; 16 | 17 | @Key 18 | public int skipCount; 19 | 20 | @Key 21 | public int maxItems; 22 | } 23 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/model/Site.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.cmis.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class Site { 9 | 10 | @Key 11 | public String id; 12 | 13 | @Key 14 | public String title; 15 | 16 | @Key 17 | public String visibility; 18 | 19 | @Key 20 | public String description; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/model/SiteEntry.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.cmis.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class SiteEntry extends Entry { 9 | @Key 10 | public Site entry; 11 | } 12 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/model/SiteList.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.cmis.example.model; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * @author jpotts 7 | */ 8 | public class SiteList { 9 | @Key 10 | public List list; 11 | } 12 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/oauth/LocalServerReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package com.alfresco.cmis.example.oauth; 16 | 17 | import org.mortbay.jetty.Connector; 18 | import org.mortbay.jetty.Request; 19 | import org.mortbay.jetty.Server; 20 | import org.mortbay.jetty.handler.AbstractHandler; 21 | 22 | import java.io.IOException; 23 | import java.io.PrintWriter; 24 | 25 | import javax.servlet.http.HttpServletRequest; 26 | import javax.servlet.http.HttpServletResponse; 27 | 28 | /** 29 | * Runs a Jetty server on a free port, waiting for OAuth to redirect to it with the verification 30 | * code. 31 | *

32 | * Mostly copied from oacurl by phopkins@google.com. 33 | *

34 | * 35 | * @author Yaniv Inbar 36 | */ 37 | public final class LocalServerReceiver implements VerificationCodeReceiver { 38 | 39 | private static final String CALLBACK_PATH = "/Callback"; 40 | private static final String LOCALHOST = "127.0.0.1"; 41 | private static final int PORT = 8080; 42 | 43 | /** Server or {@code null} before {@link #getRedirectUri()}. */ 44 | private Server server; 45 | 46 | /** Verification code or {@code null} before received. */ 47 | volatile String code; 48 | 49 | @Override 50 | public String getRedirectUri() throws Exception { 51 | server = new Server(PORT); 52 | for (Connector c : server.getConnectors()) { 53 | c.setHost(LOCALHOST); 54 | } 55 | server.addHandler(new CallbackHandler()); 56 | server.start(); 57 | return "http://" + LOCALHOST + ":" + PORT + CALLBACK_PATH; 58 | } 59 | 60 | @Override 61 | public synchronized String waitForCode() { 62 | try { 63 | this.wait(); 64 | } catch (InterruptedException exception) { 65 | // should not happen 66 | } 67 | return code; 68 | } 69 | 70 | @Override 71 | public void stop() throws Exception { 72 | if (server != null) { 73 | server.stop(); 74 | server = null; 75 | } 76 | } 77 | 78 | /** 79 | * Jetty handler that takes the verifier token passed over from the OAuth provider and stashes it 80 | * where {@link #waitForCode} will find it. 81 | */ 82 | class CallbackHandler extends AbstractHandler { 83 | 84 | @Override 85 | public void handle( 86 | String target, HttpServletRequest request, HttpServletResponse response, int dispatch) 87 | throws IOException { 88 | if (!CALLBACK_PATH.equals(target)) { 89 | return; 90 | } 91 | writeLandingHtml(response); 92 | response.flushBuffer(); 93 | ((Request) request).setHandled(true); 94 | String error = request.getParameter("error"); 95 | if (error != null) { 96 | System.out.println("Authorization failed. Error=" + error); 97 | System.out.println("Quitting."); 98 | System.exit(1); 99 | } 100 | code = request.getParameter("code"); 101 | synchronized (LocalServerReceiver.this) { 102 | LocalServerReceiver.this.notify(); 103 | } 104 | } 105 | 106 | private void writeLandingHtml(HttpServletResponse response) throws IOException { 107 | response.setStatus(HttpServletResponse.SC_OK); 108 | response.setContentType("text/html"); 109 | 110 | PrintWriter doc = response.getWriter(); 111 | doc.println(""); 112 | doc.println("OAuth 2.0 Authentication Token Recieved"); 113 | doc.println(""); 114 | doc.println("Received verification code. Closing..."); 115 | doc.println(""); 122 | doc.println(""); 123 | doc.println(""); 124 | doc.flush(); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/oauth/OAuth2ClientCredentials.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package com.alfresco.cmis.example.oauth; 15 | 16 | public class OAuth2ClientCredentials { 17 | 18 | 19 | /** Value of the "API Key". */ 20 | public static final String CLIENT_ID = "PUT YOURS HERE"; 21 | 22 | /** Value of the "API Secret". */ 23 | public static final String CLIENT_SECRET = "PUT YOURS HERE"; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /file-loader/src/main/java/com/alfresco/cmis/example/oauth/VerificationCodeReceiver.java: -------------------------------------------------------------------------------- 1 | package com.alfresco.cmis.example.oauth; 2 | /* 3 | * Copyright (c) 2011 Google Inc. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software distributed under the License 11 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 12 | * or implied. See the License for the specific language governing permissions and limitations under 13 | * the License. 14 | */ 15 | 16 | /** 17 | * Verification code receiver. 18 | * 19 | * @author Yaniv Inbar 20 | */ 21 | public interface VerificationCodeReceiver { 22 | 23 | /** Returns the redirect URI. */ 24 | String getRedirectUri() throws Exception; 25 | 26 | /** Waits for a verification code. */ 27 | String waitForCode(); 28 | 29 | /** Releases any resources and stops any processes started. */ 30 | void stop() throws Exception; 31 | } 32 | --------------------------------------------------------------------------------